diff --git a/CHANGELOG.md b/CHANGELOG.md index dfdd696bcd..4fe694decb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Keep alive feature that pings host regularly, reducing the chance of connections being dropped due to idle. Can be disabled or default frequency (10s) can be changed when calling `Waku.create`. - New `lib/utils` module for easy, dependency-less hex/bytes conversions. +- New `peers` and `randomPeer` methods on `WakuStore` and `WakuLightPush` to have a better idea of available peers; + Note that it does not check whether Waku node is currently connected to said peers. ### Changed - **Breaking**: Auto select peer if none provided for store and light push protocols. diff --git a/src/lib/select_peer.ts b/src/lib/select_peer.ts index 8e01850ec6..c509236bba 100644 --- a/src/lib/select_peer.ts +++ b/src/lib/select_peer.ts @@ -5,14 +5,18 @@ import { Peer } from 'libp2p/src/peer-store'; * Returns a pseudo-random peer that supports the given protocol. * Useful for protocols such as store and light push */ -export function selectRandomPeer( - libp2p: Libp2p, - protocol: string -): Peer | undefined { - const allPeers = Array.from(libp2p.peerStore.peers.values()); - const size = allPeers.length; - const peers = allPeers.filter((peer) => peer.protocols.includes(protocol)); +export function selectRandomPeer(peers: Peer[]): Peer | undefined { if (peers.length === 0) return; - const index = Math.round(Math.random() * (size - 1)); - return allPeers[index]; + + const index = Math.round(Math.random() * (peers.length - 1)); + return peers[index]; +} + +/** + * Returns the list of peers that supports the given protocol. + */ +export function getPeersForProtocol(libp2p: Libp2p, protocol: string): Peer[] { + return Array.from(libp2p.peerStore.peers.values()).filter((peer) => + peer.protocols.includes(protocol) + ); } diff --git a/src/lib/waku_light_push/index.ts b/src/lib/waku_light_push/index.ts index 88551756de..f46155514c 100644 --- a/src/lib/waku_light_push/index.ts +++ b/src/lib/waku_light_push/index.ts @@ -2,10 +2,11 @@ import concat from 'it-concat'; import lp from 'it-length-prefixed'; import pipe from 'it-pipe'; import Libp2p from 'libp2p'; +import { Peer } from 'libp2p/src/peer-store'; import PeerId from 'peer-id'; import { PushResponse } from '../../proto/waku/v2/light_push'; -import { selectRandomPeer } from '../select_peer'; +import { getPeersForProtocol, selectRandomPeer } from '../select_peer'; import { WakuMessage } from '../waku_message'; import { DefaultPubsubTopic } from '../waku_relay'; @@ -54,7 +55,7 @@ export class WakuLightPush { peer = this.libp2p.peerStore.get(opts.peerId); if (!peer) throw 'Peer is unknown'; } else { - peer = selectRandomPeer(this.libp2p, LightPushCodec); + peer = this.randomPeer; } if (!peer) throw 'No peer available'; if (!peer.protocols.includes(LightPushCodec)) @@ -93,4 +94,21 @@ export class WakuLightPush { } return null; } + + /** + * Returns known peers from the address book (`libp2p.peerStore`) that support + * light push protocol. Waku may or may not be currently connected to these peers. + */ + get peers(): Peer[] { + return getPeersForProtocol(this.libp2p, LightPushCodec); + } + + /** + * Returns a random peer that supports light push protocol from the address + * book (`libp2p.peerStore`). Waku may or may not be currently connected to + * this peer. + */ + get randomPeer(): Peer | undefined { + return selectRandomPeer(this.peers); + } } diff --git a/src/lib/waku_store/index.ts b/src/lib/waku_store/index.ts index c0cbe65bf1..242482cdbd 100644 --- a/src/lib/waku_store/index.ts +++ b/src/lib/waku_store/index.ts @@ -2,9 +2,10 @@ import concat from 'it-concat'; import lp from 'it-length-prefixed'; import pipe from 'it-pipe'; import Libp2p from 'libp2p'; +import { Peer } from 'libp2p/src/peer-store'; import PeerId from 'peer-id'; -import { selectRandomPeer } from '../select_peer'; +import { getPeersForProtocol, selectRandomPeer } from '../select_peer'; import { WakuMessage } from '../waku_message'; import { DefaultPubsubTopic } from '../waku_relay'; @@ -76,7 +77,7 @@ export class WakuStore { peer = this.libp2p.peerStore.get(opts.peerId); if (!peer) throw 'Peer is unknown'; } else { - peer = selectRandomPeer(this.libp2p, StoreCodec); + peer = this.randomPeer; } if (!peer) throw 'No peer available'; if (!peer.protocols.includes(StoreCodec)) @@ -164,4 +165,21 @@ export class WakuStore { } } } + + /** + * Returns known peers from the address book (`libp2p.peerStore`) that support + * store protocol. Waku may or may not be currently connected to these peers. + */ + get peers(): Peer[] { + return getPeersForProtocol(this.libp2p, StoreCodec); + } + + /** + * Returns a random peer that supports store protocol from the address + * book (`libp2p.peerStore`). Waku may or may not be currently connected to + * this peer. + */ + get randomPeer(): Peer | undefined { + return selectRandomPeer(this.peers); + } }