@waku/discovery
Version:
Contains various discovery mechanisms: DNS Discovery (EIP-1459, Peer Exchange, Local Peer Cache Discovery.
93 lines • 3.08 kB
JavaScript
import { StreamManager } from "@waku/core";
import { EnrDecoder } from "@waku/enr";
import { ProtocolError } from "@waku/interfaces";
import { isDefined } from "@waku/utils";
import { Logger } from "@waku/utils";
import all from "it-all";
import * as lp from "it-length-prefixed";
import { pipe } from "it-pipe";
import { Uint8ArrayList } from "uint8arraylist";
import { PeerExchangeRPC } from "./rpc.js";
export const PeerExchangeCodec = "/vac/waku/peer-exchange/2.0.0-alpha1";
const log = new Logger("peer-exchange");
/**
* Implementation of the Peer Exchange protocol (https://rfc.vac.dev/spec/34/)
*/
export class WakuPeerExchange {
components;
streamManager;
/**
* @param components - libp2p components
*/
constructor(components) {
this.components = components;
this.streamManager = new StreamManager(PeerExchangeCodec, components);
}
/**
* Make a peer exchange query to a peer
*/
async query(params) {
const { numPeers, peerId } = params;
const rpcQuery = PeerExchangeRPC.createRequest({
numPeers: BigInt(numPeers)
});
const peer = await this.components.peerStore.get(peerId);
if (!peer) {
return {
peerInfos: null,
error: ProtocolError.NO_PEER_AVAILABLE
};
}
let stream;
try {
stream = await this.streamManager.getStream(peerId);
}
catch (err) {
log.error("Failed to get stream", err);
return {
peerInfos: null,
error: ProtocolError.NO_STREAM_AVAILABLE
};
}
const res = await pipe([rpcQuery.encode()], lp.encode, stream, lp.decode, async (source) => await all(source));
try {
const bytes = new Uint8ArrayList();
res.forEach((chunk) => {
bytes.append(chunk);
});
const { response } = PeerExchangeRPC.decode(bytes);
if (!response) {
log.error("PeerExchangeRPC message did not contains a `response` field");
return {
peerInfos: null,
error: ProtocolError.EMPTY_PAYLOAD
};
}
const peerInfos = await Promise.all(response.peerInfos
.map((peerInfo) => peerInfo.enr)
.filter(isDefined)
.map(async (enr) => {
return { ENR: await EnrDecoder.fromRLP(enr) };
}));
return {
peerInfos,
error: null
};
}
catch (err) {
log.error("Failed to decode push reply", err);
return {
peerInfos: null,
error: ProtocolError.DECODE_FAILED
};
}
}
}
/**
*
* @returns A function that creates a new peer exchange protocol
*/
export function wakuPeerExchange() {
return (components) => new WakuPeerExchange(components);
}
//# sourceMappingURL=waku_peer_exchange.js.map