104 lines
3.1 KiB
TypeScript
Raw Normal View History

2022-01-13 11:33:26 +11:00
import debug from 'debug';
2022-01-13 14:28:45 +11:00
import { Multiaddr } from 'multiaddr';
2022-01-13 11:33:26 +11:00
import { DnsNodeDiscovery } from './dns';
import { getNodesFromHostedJson, getPseudoRandomSubset } from './index';
const dbg = debug('waku:discovery:bootstrap');
2022-01-13 14:28:45 +11:00
export const DefaultMaxPeers = 1;
export type BootstrapFn = () => Promise<Multiaddr[]>;
2022-01-13 11:33:26 +11:00
/**
* Setup discovery method used to bootstrap.
*
* Only one method is used. `default`, `peers`, `getPeers` and `enr` options are mutually exclusive.
*/
export interface BootstrapOptions {
/**
* The maximum of peers to connect to as part of the bootstrap process.
*
2022-01-13 15:53:22 +11:00
* @default [[DefaultMaxPeers]]
2022-01-13 11:33:26 +11:00
*/
maxPeers?: number;
/**
2022-01-13 14:28:45 +11:00
* Use the default discovery method. Overrides all other options but `maxPeers`
2022-01-13 11:33:26 +11:00
*
* The default discovery method is likely to change overtime as new discovery
* methods are implemented.
*
* @default false
*/
default?: boolean;
/**
* Multiaddrs of peers to connect to.
*/
peers?: string[];
/**
* Getter that retrieve multiaddrs of peers to connect to.
*/
2022-01-13 14:28:45 +11:00
getPeers?: () => Promise<string[] | Multiaddr[]>;
2022-01-13 11:33:26 +11:00
/**
* An EIP-1459 ENR Tree URL. For example:
* "enrtree://AOFTICU2XWDULNLZGRMQS4RIZPAZEHYMV4FYHAPW563HNRAOERP7C@test.nodes.vac.dev"
*/
enrUrl?: string;
}
/**
* Parse the bootstrap options and returns an async function that returns node addresses upon invocation.
*/
2022-01-13 14:28:45 +11:00
export function parseBootstrap(opts: BootstrapOptions): BootstrapFn {
const maxPeers = opts.maxPeers ?? DefaultMaxPeers;
if (opts.default) {
dbg('Bootstrap: Use hosted list of peers.');
2022-01-13 11:33:26 +11:00
2022-01-13 14:28:45 +11:00
return getNodesFromHostedJson.bind({}, undefined, undefined, maxPeers);
} else if (opts.peers !== undefined && opts.peers.length > 0) {
dbg('Bootstrap: Use provided list of peers.');
2022-01-13 11:33:26 +11:00
2022-01-13 14:28:45 +11:00
const allPeers: Multiaddr[] = opts.peers.map(
(node: string) => new Multiaddr(node)
);
const peers = getPseudoRandomSubset(allPeers, maxPeers);
return (): Promise<Multiaddr[]> => Promise.resolve(peers);
} else if (typeof opts.getPeers === 'function') {
dbg('Bootstrap: Use provided getPeers function.');
const getPeers = opts.getPeers;
2022-01-13 11:33:26 +11:00
2022-01-13 14:28:45 +11:00
return async (): Promise<Multiaddr[]> => {
const allPeers = await getPeers();
return getPseudoRandomSubset<string | Multiaddr>(allPeers, maxPeers).map(
(node) => new Multiaddr(node)
);
};
} else if (opts.enrUrl) {
const enrUrl = opts.enrUrl;
dbg('Bootstrap: Use provided EIP-1459 ENR Tree URL.');
2022-01-13 11:33:26 +11:00
2022-01-13 14:28:45 +11:00
const dns = DnsNodeDiscovery.dnsOverHttp();
2022-01-13 11:33:26 +11:00
2022-01-13 14:28:45 +11:00
return async (): Promise<Multiaddr[]> => {
const enrs = await dns.getPeers(maxPeers, [enrUrl]);
const addresses: Multiaddr[] = [];
enrs.forEach((enr) => {
if (!enr.multiaddrs) return;
enr.multiaddrs.forEach((ma: Multiaddr) => {
// Only return secure websocket addresses
if (ma.protoNames().includes('wss')) {
addresses.push(ma);
}
});
});
return addresses;
};
2022-01-13 11:33:26 +11:00
} else {
2022-01-13 14:28:45 +11:00
dbg('No bootstrap method specified, no peer will be returned');
return (): Promise<Multiaddr[]> => Promise.resolve([]);
2022-01-13 11:33:26 +11:00
}
}