diff --git a/CHANGELOG.md b/CHANGELOG.md index af97df1838..8901263351 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Test: Upgrade nim-waku node to v0.6. +- **Breaking**: Renamed `getBootstrapNodes` to `getNodesFromHostedJson`. - Minimum node version changed to 16. ### Fixed diff --git a/src/index.ts b/src/index.ts index 435ec291ae..4887685ba3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -export { getBootstrapNodes } from './lib/discovery'; +export { getNodesFromHostedJson, getPseudoRandomSubset } from './lib/discovery'; export * as utils from './lib/utils'; diff --git a/src/lib/discovery/hosted_json.ts b/src/lib/discovery/hosted_json.ts new file mode 100644 index 0000000000..bfabea3aca --- /dev/null +++ b/src/lib/discovery/hosted_json.ts @@ -0,0 +1,74 @@ +/** + * GET list of nodes from remote HTTP host. + * + * Default behavior is to return nodes hosted by Status. + * + * @param path The property path to access the node list. The result should be + * a string, a string array or an object. If the result is an object then the + * values of the objects are used as multiaddresses. For example, if the GET + * request returns `{ foo: { bar: [address1, address2] } }` then `path` should be + * `[ "foo", "bar" ]`. + * @param url Remote host containing bootstrap peers in JSON format. + * @param wantedNumber The number of connections desired. Defaults to [DefaultWantedNumber]. + * + * @returns An array of multiaddresses. + * @throws If the remote host is unreachable or the response cannot be parsed + * according to the passed _path_. + */ +import axios from 'axios'; +import debug from 'debug'; +import { Multiaddr } from 'multiaddr'; + +import { getPseudoRandomSubset } from './index'; +const dbg = debug('waku:discovery'); + +const DefaultWantedNumber = 1; + +export async function getNodesFromHostedJson( + path: string[] = ['fleets', 'wakuv2.prod', 'waku-websocket'], + url = 'https://fleets.status.im/', + wantedNumber: number = DefaultWantedNumber +): Promise { + if (wantedNumber <= 0) { + return []; + } + + const res = await axios.get(url, { + headers: { 'Content-Type': 'application/json' }, + }); + + let nodes = res.data; + + for (const prop of path) { + if (nodes[prop] === undefined) { + dbg( + `Failed to retrieve bootstrap nodes: ${prop} does not exist on `, + nodes + ); + throw `Failed to retrieve bootstrap nodes: ${prop} does not exist on ${JSON.stringify( + nodes + )}`; + } + nodes = nodes[prop]; + } + + if (Array.isArray(nodes)) { + return getPseudoRandomSubset(nodes, wantedNumber).map( + (node: string) => node + ); + } + + if (typeof nodes === 'string') { + return [nodes]; + } + + if (typeof nodes === 'object') { + nodes = Object.values(nodes) as string[]; + nodes = nodes.map((node: string) => new Multiaddr(node)); + return getPseudoRandomSubset(nodes, wantedNumber); + } + + throw `Failed to retrieve bootstrap nodes: response format is not supported: ${JSON.stringify( + nodes + )}`; +} diff --git a/src/lib/discovery/index.ts b/src/lib/discovery/index.ts index 6fabcf5fa6..09eeb32682 100644 --- a/src/lib/discovery/index.ts +++ b/src/lib/discovery/index.ts @@ -1,73 +1,6 @@ -import axios from 'axios'; -import debug from 'debug'; import { shuffle } from 'libp2p-gossipsub/src/utils'; -const dbg = debug('waku:discovery'); - -const DefaultWantedNumber = 1; - -/** - * GET list of nodes from remote HTTP host. - * - * Default behavior is to return nodes hosted by Status. - * - * @param path The property path to access the node list. The result should be - * a string, a string array or an object. If the result is an object then the - * values of the objects are used as multiaddresses. For example, if the GET - * request returns `{ foo: { bar: [address1, address2] } }` then `path` should be - * `[ "foo", "bar" ]`. - * @param url Remote host containing bootstrap peers in JSON format. - * @param wantedNumber The number of connections desired. Defaults to [DefaultWantedNumber]. - * - * @returns An array of multiaddresses. - * @throws If the remote host is unreachable or the response cannot be parsed - * according to the passed _path_. - */ -export async function getBootstrapNodes( - path: string[] = ['fleets', 'wakuv2.prod', 'waku-websocket'], - url = 'https://fleets.status.im/', - wantedNumber: number = DefaultWantedNumber -): Promise { - if (wantedNumber <= 0) { - return []; - } - - const res = await axios.get(url, { - headers: { 'Content-Type': 'application/json' }, - }); - - let nodes = res.data; - - for (const prop of path) { - if (nodes[prop] === undefined) { - dbg( - `Failed to retrieve bootstrap nodes: ${prop} does not exist on `, - nodes - ); - throw `Failed to retrieve bootstrap nodes: ${prop} does not exist on ${JSON.stringify( - nodes - )}`; - } - nodes = nodes[prop]; - } - - if (Array.isArray(nodes)) { - return getPseudoRandomSubset(nodes, wantedNumber); - } - - if (typeof nodes === 'string') { - return [nodes]; - } - - if (typeof nodes === 'object') { - nodes = Object.values(nodes); - return getPseudoRandomSubset(nodes, wantedNumber); - } - - throw `Failed to retrieve bootstrap nodes: response format is not supported: ${JSON.stringify( - nodes - )}`; -} +export { getNodesFromHostedJson } from './hosted_json'; export function getPseudoRandomSubset( values: string[], diff --git a/src/lib/waku.ts b/src/lib/waku.ts index 6900ab6e07..f5da1c5d3e 100644 --- a/src/lib/waku.ts +++ b/src/lib/waku.ts @@ -18,7 +18,7 @@ import Ping from 'libp2p/src/ping'; import { Multiaddr, multiaddr } from 'multiaddr'; import PeerId from 'peer-id'; -import { getBootstrapNodes } from './discovery'; +import { getNodesFromHostedJson } from './discovery'; import { getPeersForProtocol } from './select_peer'; import { LightPushCodec, WakuLightPush } from './waku_light_push'; import { WakuMessage } from './waku_message'; @@ -87,7 +87,7 @@ export interface CreateOptions { * Use libp2p-bootstrap to discover and connect to new nodes. * * You can pass: - * - `true` to use {@link getBootstrapNodes}, + * - `true` to use {@link getNodesFromHostedJson}, * - an array of multiaddresses, * - a function that returns an array of multiaddresses (or Promise of). * @@ -192,7 +192,7 @@ export class Waku { let bootstrap: undefined | (() => string[] | Promise); if (options.bootstrap === true) { - bootstrap = getBootstrapNodes; + bootstrap = getNodesFromHostedJson; } else if (Array.isArray(options.bootstrap)) { bootstrap = (): string[] => { return options.bootstrap as string[];