OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-proto-peer / test / peer-discovery.test.js

50 lines · javascript ref:
// Option 2 discovery: a peer is findable from its DID ALONE — no pre-shared serverKey/repoKey,
// nothing written to the DID doc. The peer announces on discoveryTopic(did); a resolver derives
// the same topic from the DID, connects, and reads the peer's coords over get-coords. (A bridge
// then replicates + verifies the repo signs against the DID key — the connect-time auth.)

import test from 'brittle'
import { mkdtempSync, rmSync } from 'bare-fs'
import { tmpdir } from 'bare-os'
import { join } from 'bare-path'
import c from 'compact-encoding'
import Hyperswarm from 'hyperswarm'
import createTestnet from '@hyperswarm/testnet'
import ProtomuxRPC from 'protomux-rpc'
import { discoveryTopic } from 'atproto-identity/lib/discovery.js'
import { Peer } from '../lib/peer.js'

const MNEMONIC = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
const RPC_PROTOCOL = 'hyper-proto-peer/rpc/v1'

test('a peer is discoverable by DID alone — no pre-shared keys, no DID-doc entry', async (t) => {
  const testnet = await createTestnet(3)
  const dir = mkdtempSync(join(tmpdir(), 'disc-'))
  const peer = await Peer.fromMnemonic({ storage: dir, mnemonic: MNEMONIC, handle: 'alice.7rnx.net', pdsUrl: 'https://pds.7rnx.net' })
  await peer.write({ collection: 'app.bsky.feed.post', rkey: '3a', record: { $type: 'app.bsky.feed.post', text: 'findable', createdAt: '2026-07-03T00:00:00.000Z' } })
  const peerSwarm = new Hyperswarm({ bootstrap: testnet.bootstrap })
  const serving = peer.serve(peerSwarm)
  await serving.ready()

  // a resolver that knows ONLY the DID (as a bridge would, from bsky's getRepo?did=X)
  const resolverSwarm = new Hyperswarm({ bootstrap: testnet.bootstrap })
  const topic = discoveryTopic(peer.did)
  const conn = await new Promise((resolve) => {
    resolverSwarm.once('connection', resolve)
    resolverSwarm.join(topic, { client: true, server: false })
    resolverSwarm.flush()
  })
  const rpc = new ProtomuxRPC(conn, { protocol: RPC_PROTOCOL, valueEncoding: c.json })
  const coords = await rpc.request('get-coords', {})

  t.teardown(async () => {
    serving.close(); await peerSwarm.destroy(); await resolverSwarm.destroy()
    await peer.close(); await testnet.destroy(); rmSync(dir, { recursive: true, force: true })
  })

  t.is(coords.did, peer.did, 'resolved the peer over the DID-derived topic')
  t.is(coords.repoKey, peer.repoKeyHex, 'got repoKey from only the DID (no pre-shared keys)')
  t.is(coords.firehoseKey, peer.firehoseKeyHex, 'got firehoseKey from only the DID')
  t.ok(coords.serverKey, 'got the peer serverKey')
})