UNPKG

hyperns-service

Version:
111 lines (86 loc) 2.72 kB
const { EventEmitter } = require('events') const IdEnc = require('hypercore-id-encoding') const cenc = require('compact-encoding') const BlindPeerClient = require('blind-peer/client.js') const b4a = require('b4a') const HyperNsService = require('.') const opEncoding = HyperNsService.VALUE_ENCODING class HyperNsRegisterClient extends EventEmitter { constructor (blindPeerKey, autobaseKey, swarm) { super() this.blindPeerKey = IdEnc.decode(blindPeerKey) this.autobaseKey = IdEnc.decode(autobaseKey) this.swarm = swarm this._boundConnHandler = this._connHandler.bind(this) this.swarm.on('connection', this._boundConnHandler) this._peer = null } open () { this.swarm.joinPeer(this.blindPeerKey) } close () { this.emit('closing') this.swarm.off('connection', this._boundConnHandler) // Note: this can have side effects if we're connecting to that // peer for other reasons (ignoring that potential issue for now) this.swarm.leavePeer(this.blindPeerKey) } async _connHandler (conn) { if (!b4a.equals(conn.remotePublicKey, this.blindPeerKey)) return this.emit('connection-open') conn.on('close', () => { this.emit('connection-close') this._peer = null }) this._peer = new BlindPeerClient(conn) } async ensureConnected (timeoutMs = 5000) { if (this._peer) return await new Promise((resolve, reject) => { let cancelHandler = null let timeout = null const cleanup = () => { this.removeListener('closing', cancelHandler) clearTimeout(timeout) } timeout = setTimeout( () => { cleanup() reject(new Error('Ensure connected timed out')) }, timeoutMs ) cancelHandler = () => { cleanup() reject(new Error('Register client is closing')) } this.on('closing', cancelHandler) this.once('connection-open', () => { cleanup() resolve() }) }) } async register (name, publicKey, blindPeers) { blindPeers = blindPeers || [] const record = { name, publicKey: IdEnc.decode(publicKey), blindPeers } // Note: We could also await once(this, 'connection-open') with a timeout, // for a slightly friendlier UX if (this._peer === null) throw new Error('Not connected to blind peer') const message = { op: HyperNsService.OPS.ADD_RECORD, record } const reply = await this._peer.post({ autobase: this.autobaseKey, message: cenc.encode(opEncoding, message) }) const autobaseLength = reply.length return autobaseLength } } module.exports = HyperNsRegisterClient