Skip to content

Commit 9f198dd

Browse files
authored
feat: add bootstrapPeers option and refactor sdk (#1871)
* move relay related code * move libp2p to utils * define CreateWakuNodeOptions * improve options * make libp2p use from create function * add bootstrapPeers option * fix lint * fix types, imports * fix exports * use bootstrap along default bootstrap * fix test as REST does not return peer though connection is made * rollback condition change * enable gossipSub back for every node
1 parent fcc3f10 commit 9f198dd

File tree

11 files changed

+212
-248
lines changed

11 files changed

+212
-248
lines changed

package-lock.json

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/interfaces/src/protocols.ts

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ export type ProtocolCreateOptions = {
8787
* Use recommended bootstrap method to discovery and connect to new nodes.
8888
*/
8989
defaultBootstrap?: boolean;
90+
/**
91+
* List of peers to use to bootstrap the node. Ignored if defaultBootstrap is set to true.
92+
*/
93+
bootstrapPeers?: string[];
9094
};
9195

9296
export type Callback<T extends IDecodedMessage> = (

packages/sdk/package.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@
7373
"@waku/peer-exchange": "^0.0.19",
7474
"@waku/relay": "0.0.9",
7575
"@waku/utils": "0.0.14",
76-
"libp2p": "^1.1.2"
76+
"libp2p": "^1.1.2",
77+
"@libp2p/bootstrap": "^10.0.11"
7778
},
7879
"devDependencies": {
7980
"@chainsafe/libp2p-gossipsub": "^12.0.0",
@@ -86,6 +87,9 @@
8687
"npm-run-all": "^4.1.5",
8788
"rollup": "^4.12.0"
8889
},
90+
"peerDependencies": {
91+
"@libp2p/bootstrap": "^10"
92+
},
8993
"files": [
9094
"dist",
9195
"bundle",

packages/sdk/src/create.ts

+8-203
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,22 @@
1-
import type { GossipSub } from "@chainsafe/libp2p-gossipsub";
2-
import { noise } from "@chainsafe/libp2p-noise";
3-
import { identify } from "@libp2p/identify";
4-
import type { PeerDiscovery } from "@libp2p/interface";
5-
import { mplex } from "@libp2p/mplex";
6-
import { ping } from "@libp2p/ping";
7-
import { webSockets } from "@libp2p/websockets";
8-
import { all as filterAll } from "@libp2p/websockets/filters";
9-
import { wakuFilter, wakuLightPush, wakuMetadata, wakuStore } from "@waku/core";
10-
import { enrTree, wakuDnsDiscovery } from "@waku/dns-discovery";
11-
import {
12-
type CreateLibp2pOptions,
13-
DefaultPubsubTopic,
14-
type FullNode,
15-
type IMetadata,
16-
type Libp2p,
17-
type Libp2pComponents,
18-
type LightNode,
19-
type ProtocolCreateOptions,
20-
PubsubTopic,
21-
type ShardInfo
22-
} from "@waku/interfaces";
23-
import { wakuLocalPeerCacheDiscovery } from "@waku/local-peer-cache-discovery";
24-
import { wakuPeerExchangeDiscovery } from "@waku/peer-exchange";
25-
import { RelayCreateOptions, wakuGossipSub, wakuRelay } from "@waku/relay";
26-
import { ensureShardingConfigured } from "@waku/utils";
27-
import { createLibp2p } from "libp2p";
1+
import { wakuFilter, wakuLightPush, wakuStore } from "@waku/core";
2+
import { type Libp2pComponents, type LightNode } from "@waku/interfaces";
283

29-
import { DefaultUserAgent, WakuNode, WakuOptions } from "./waku.js";
30-
31-
const DEFAULT_NODE_REQUIREMENTS = {
32-
lightPush: 1,
33-
filter: 1,
34-
store: 1
35-
};
4+
import { createLibp2pAndUpdateOptions } from "./utils/libp2p.js";
5+
import { CreateWakuNodeOptions, WakuNode, WakuOptions } from "./waku.js";
366

377
export { Libp2pComponents };
388

399
/**
4010
* Create a Waku node configured to use autosharding or static sharding.
4111
*/
4212
export async function createNode(
43-
options?: ProtocolCreateOptions &
44-
Partial<WakuOptions> &
45-
Partial<RelayCreateOptions>
13+
options: CreateWakuNodeOptions = { pubsubTopics: [] }
4614
): Promise<LightNode> {
47-
options = options ?? { pubsubTopics: [] };
48-
4915
if (!options.shardInfo) {
5016
throw new Error("Shard info must be set");
5117
}
5218

53-
const shardInfo = ensureShardingConfigured(options.shardInfo);
54-
options.pubsubTopics = shardInfo.pubsubTopics;
55-
options.shardInfo = shardInfo.shardInfo;
56-
57-
const libp2pOptions = options?.libp2p ?? {};
58-
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
59-
if (options?.defaultBootstrap) {
60-
peerDiscovery.push(...defaultPeerDiscoveries(shardInfo.pubsubTopics));
61-
Object.assign(libp2pOptions, { peerDiscovery });
62-
}
63-
64-
const libp2p = await defaultLibp2p(
65-
shardInfo.shardInfo,
66-
wakuGossipSub(options),
67-
libp2pOptions,
68-
options?.userAgent
69-
);
19+
const libp2p = await createLibp2pAndUpdateOptions(options);
7020

7121
const store = wakuStore(options);
7222
const lightPush = wakuLightPush(options);
@@ -87,30 +37,9 @@ export async function createNode(
8737
* Uses Waku Filter V2 by default.
8838
*/
8939
export async function createLightNode(
90-
options?: ProtocolCreateOptions & Partial<WakuOptions>
40+
options: CreateWakuNodeOptions = {}
9141
): Promise<LightNode> {
92-
options = options ?? {};
93-
94-
const shardInfo = options.shardInfo
95-
? ensureShardingConfigured(options.shardInfo)
96-
: undefined;
97-
98-
options.pubsubTopics = shardInfo?.pubsubTopics ??
99-
options.pubsubTopics ?? [DefaultPubsubTopic];
100-
101-
const libp2pOptions = options?.libp2p ?? {};
102-
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
103-
if (options?.defaultBootstrap) {
104-
peerDiscovery.push(...defaultPeerDiscoveries(options.pubsubTopics));
105-
Object.assign(libp2pOptions, { peerDiscovery });
106-
}
107-
108-
const libp2p = await defaultLibp2p(
109-
shardInfo?.shardInfo,
110-
wakuGossipSub(options),
111-
libp2pOptions,
112-
options?.userAgent
113-
);
42+
const libp2p = await createLibp2pAndUpdateOptions(options);
11443

11544
const store = wakuStore(options);
11645
const lightPush = wakuLightPush(options);
@@ -124,127 +53,3 @@ export async function createLightNode(
12453
filter
12554
) as LightNode;
12655
}
127-
128-
/**
129-
* Create a Waku node that uses all Waku protocols.
130-
*
131-
* This helper is not recommended except if:
132-
* - you are interfacing with nwaku v0.11 or below
133-
* - you are doing some form of testing
134-
*
135-
* If you are building a full node, it is recommended to use
136-
* [nwaku](github.com/status-im/nwaku) and its JSON RPC API or wip REST API.
137-
*
138-
* @see https://github.com/status-im/nwaku/issues/1085
139-
* @internal
140-
*/
141-
export async function createFullNode(
142-
options?: ProtocolCreateOptions &
143-
Partial<WakuOptions> &
144-
Partial<RelayCreateOptions>
145-
): Promise<FullNode> {
146-
options = options ?? { pubsubTopics: [] };
147-
148-
const shardInfo = options.shardInfo
149-
? ensureShardingConfigured(options.shardInfo)
150-
: undefined;
151-
152-
const pubsubTopics = shardInfo?.pubsubTopics ??
153-
options.pubsubTopics ?? [DefaultPubsubTopic];
154-
options.pubsubTopics = pubsubTopics;
155-
options.shardInfo = shardInfo?.shardInfo;
156-
157-
const libp2pOptions = options?.libp2p ?? {};
158-
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
159-
if (options?.defaultBootstrap) {
160-
peerDiscovery.push(...defaultPeerDiscoveries(pubsubTopics));
161-
Object.assign(libp2pOptions, { peerDiscovery });
162-
}
163-
164-
const libp2p = await defaultLibp2p(
165-
shardInfo?.shardInfo,
166-
wakuGossipSub(options),
167-
libp2pOptions,
168-
options?.userAgent
169-
);
170-
171-
const store = wakuStore(options);
172-
const lightPush = wakuLightPush(options);
173-
const filter = wakuFilter(options);
174-
const relay = wakuRelay(pubsubTopics);
175-
176-
return new WakuNode(
177-
options as WakuOptions,
178-
libp2p,
179-
store,
180-
lightPush,
181-
filter,
182-
relay
183-
) as FullNode;
184-
}
185-
186-
export function defaultPeerDiscoveries(
187-
pubsubTopics: PubsubTopic[]
188-
): ((components: Libp2pComponents) => PeerDiscovery)[] {
189-
const discoveries = [
190-
wakuDnsDiscovery([enrTree["PROD"]], DEFAULT_NODE_REQUIREMENTS),
191-
wakuLocalPeerCacheDiscovery(),
192-
wakuPeerExchangeDiscovery(pubsubTopics)
193-
];
194-
return discoveries;
195-
}
196-
197-
type PubsubService = {
198-
pubsub?: (components: Libp2pComponents) => GossipSub;
199-
};
200-
201-
type MetadataService = {
202-
metadata?: (components: Libp2pComponents) => IMetadata;
203-
};
204-
205-
export async function defaultLibp2p(
206-
shardInfo?: ShardInfo,
207-
wakuGossipSub?: PubsubService["pubsub"],
208-
options?: Partial<CreateLibp2pOptions>,
209-
userAgent?: string
210-
): Promise<Libp2p> {
211-
if (!options?.hideWebSocketInfo && process.env.NODE_ENV !== "test") {
212-
/* eslint-disable no-console */
213-
console.info(
214-
"%cIgnore WebSocket connection failures",
215-
"background: gray; color: white; font-size: x-large"
216-
);
217-
console.info(
218-
"%cWaku tries to discover peers and some of them are expected to fail",
219-
"background: gray; color: white; font-size: x-large"
220-
);
221-
/* eslint-enable no-console */
222-
}
223-
224-
const pubsubService: PubsubService = wakuGossipSub
225-
? { pubsub: wakuGossipSub }
226-
: {};
227-
228-
const metadataService: MetadataService = shardInfo
229-
? { metadata: wakuMetadata(shardInfo) }
230-
: {};
231-
232-
return createLibp2p({
233-
connectionManager: {
234-
minConnections: 1
235-
},
236-
transports: [webSockets({ filter: filterAll })],
237-
streamMuxers: [mplex()],
238-
connectionEncryption: [noise()],
239-
...options,
240-
services: {
241-
identify: identify({
242-
agentVersion: userAgent ?? DefaultUserAgent
243-
}),
244-
ping: ping(),
245-
...metadataService,
246-
...pubsubService,
247-
...options?.services
248-
}
249-
}) as any as Libp2p; // TODO: make libp2p include it;
250-
}

packages/sdk/src/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ export {
77

88
export { utf8ToBytes, bytesToUtf8 } from "@waku/utils/bytes";
99

10-
export * from "./content_topic.js";
10+
export { defaultLibp2p } from "./utils/libp2p.js";
11+
export * from "./utils/content_topic.js";
1112
export * from "./waku.js";
1213
export * from "./create.js";
1314
export * as waku from "@waku/core";

0 commit comments

Comments
 (0)