#!/usr/bin/env node
// Hello World — JS side of the Hyperswarm interop test.
//
// Joins the live public DHT on a shared topic, discovers peers,
// and exchanges messages via protomux "godot-rpc" channel (type 0).
//
// Usage: node hello.mjs [topic]
// topic defaults to "hello-hyperswarm"
import Hyperswarm from 'hyperswarm'
import Protomux from 'protomux'
import c from 'compact-encoding'
import crypto from 'crypto'
const topicStr = process.argv[2] || 'hello-hyperswarm'
const topicHash = crypto.createHash('sha256').update(topicStr).digest()
console.log(`[hello-js] topic: "${topicStr}"`)
console.log(`[hello-js] topic hash: ${topicHash.toString('hex').slice(0, 16)}...`)
console.log(`[hello-js] pid: ${process.pid}`)
console.log(`[hello-js] joining live DHT...\n`)
const swarm = new Hyperswarm()
let seq = 0
swarm.on('connection', (conn, peerInfo) => {
const pk = peerInfo.publicKey.toString('hex').slice(0, 12)
console.log(`[connected] peer ${pk} (client=${peerInfo.client})`)
const mux = Protomux.from(conn)
const channel = mux.createChannel({
protocol: 'godot-rpc',
id: null,
unique: false
})
const msg = channel.addMessage({
encoding: c.raw,
onmessage (buf) {
try {
const text = buf.toString('utf8')
console.log(`[recv] ${text}`)
} catch {
console.log(`[recv] <binary ${buf.length} bytes>`)
}
}
})
channel.open()
const iv = setInterval(() => {
if (conn.destroyed || channel.closed) {
clearInterval(iv)
return
}
seq++
const payload = JSON.stringify({
from: 'js',
msg: 'Hello World',
seq
})
msg.send(Buffer.from(payload))
console.log(`[send] ${payload}`)
}, 5000)
conn.on('close', () => {
clearInterval(iv)
console.log(`[disconnected] peer ${pk}`)
})
conn.on('error', () => {})
})
const discovery = swarm.join(topicHash, { server: true, client: true })
await discovery.flushed()
console.log('[hello-js] topic joined, waiting for peers...\n')
// Graceful shutdown
process.on('SIGINT', async () => {
console.log('\n[hello-js] shutting down...')
await swarm.destroy()
process.exit(0)
})