chore: simplify protocol creation (#2283)

* simplify protocol creation

* up relay

* fix check

* up size limit config
This commit is contained in:
Sasha 2025-02-25 18:41:32 +01:00 committed by GitHub
parent 87a918d9cc
commit 0ede57f387
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 108 additions and 102 deletions

View File

@ -40,22 +40,22 @@ module.exports = [
{ {
name: "Privacy preserving protocols", name: "Privacy preserving protocols",
path: "packages/relay/bundle/index.js", path: "packages/relay/bundle/index.js",
import: "{ wakuRelay }", import: "{ Relay }",
}, },
{ {
name: "Waku Filter", name: "Waku Filter",
path: "packages/sdk/bundle/index.js", path: "packages/sdk/bundle/index.js",
import: "{ wakuFilter }", import: "{ Filter }",
}, },
{ {
name: "Waku LightPush", name: "Waku LightPush",
path: "packages/sdk/bundle/index.js", path: "packages/sdk/bundle/index.js",
import: "{ wakuLightPush }", import: "{ LightPush }",
}, },
{ {
name: "History retrieval protocols", name: "History retrieval protocols",
path: "packages/sdk/bundle/index.js", path: "packages/sdk/bundle/index.js",
import: "{ wakuStore }", import: "{ Store }",
}, },
{ {
name: "Deterministic Message Hashing", name: "Deterministic Message Hashing",

View File

@ -1,7 +1,7 @@
import type { CreateNodeOptions, RelayNode } from "@waku/interfaces"; import type { CreateNodeOptions, RelayNode } from "@waku/interfaces";
import { createLibp2pAndUpdateOptions, WakuNode } from "@waku/sdk"; import { createLibp2pAndUpdateOptions, WakuNode } from "@waku/sdk";
import { RelayCreateOptions, wakuGossipSub, wakuRelay } from "./relay.js"; import { Relay, RelayCreateOptions, wakuGossipSub } from "./relay.js";
/** /**
* Create a Waku node that uses Waku Relay to send and receive messages, * Create a Waku node that uses Waku Relay to send and receive messages,
@ -27,7 +27,10 @@ export async function createRelayNode(
}; };
const { libp2p, pubsubTopics } = await createLibp2pAndUpdateOptions(options); const { libp2p, pubsubTopics } = await createLibp2pAndUpdateOptions(options);
const relay = wakuRelay(pubsubTopics || [])(libp2p); const relay = new Relay({
pubsubTopics: pubsubTopics || [],
libp2p
});
return new WakuNode( return new WakuNode(
pubsubTopics, pubsubTopics,

View File

@ -42,11 +42,16 @@ export type Observer<T extends IDecodedMessage> = {
export type RelayCreateOptions = CreateNodeOptions & GossipsubOpts; export type RelayCreateOptions = CreateNodeOptions & GossipsubOpts;
export type ContentTopic = string; export type ContentTopic = string;
type RelayConstructorParams = {
libp2p: Libp2p;
pubsubTopics: PubsubTopic[];
};
/** /**
* Implements the [Waku v2 Relay protocol](https://rfc.vac.dev/spec/11/). * Implements the [Waku v2 Relay protocol](https://rfc.vac.dev/spec/11/).
* Throws if libp2p.pubsub does not support Waku Relay * Throws if libp2p.pubsub does not support Waku Relay
*/ */
class Relay implements IRelay { export class Relay implements IRelay {
public readonly pubsubTopics: Set<PubsubTopic>; public readonly pubsubTopics: Set<PubsubTopic>;
private defaultDecoder: IDecoder<IDecodedMessage>; private defaultDecoder: IDecoder<IDecodedMessage>;
@ -59,15 +64,15 @@ class Relay implements IRelay {
*/ */
private observers: Map<PubsubTopic, Map<ContentTopic, Set<unknown>>>; private observers: Map<PubsubTopic, Map<ContentTopic, Set<unknown>>>;
public constructor(libp2p: Libp2p, pubsubTopics: PubsubTopic[]) { public constructor(params: RelayConstructorParams) {
if (!this.isRelayPubsub(libp2p.services.pubsub)) { if (!this.isRelayPubsub(params.libp2p.services.pubsub)) {
throw Error( throw Error(
`Failed to initialize Relay. libp2p.pubsub does not support ${Relay.multicodec}` `Failed to initialize Relay. libp2p.pubsub does not support ${Relay.multicodec}`
); );
} }
this.gossipSub = libp2p.services.pubsub as GossipSub; this.gossipSub = params.libp2p.services.pubsub as GossipSub;
this.pubsubTopics = new Set(pubsubTopics); this.pubsubTopics = new Set(params.pubsubTopics);
if (this.gossipSub.isStarted()) { if (this.gossipSub.isStarted()) {
this.subscribeToAllTopics(); this.subscribeToAllTopics();
@ -76,7 +81,7 @@ class Relay implements IRelay {
this.observers = new Map(); this.observers = new Map();
// TODO: User might want to decide what decoder should be used (e.g. for RLN) // TODO: User might want to decide what decoder should be used (e.g. for RLN)
this.defaultDecoder = new TopicOnlyDecoder(pubsubTopics[0]); this.defaultDecoder = new TopicOnlyDecoder(params.pubsubTopics[0]);
} }
/** /**
@ -311,12 +316,6 @@ class Relay implements IRelay {
} }
} }
export function wakuRelay(
pubsubTopics: PubsubTopic[]
): (libp2p: Libp2p) => IRelay {
return (libp2p: Libp2p) => new Relay(libp2p, pubsubTopics);
}
export function wakuGossipSub( export function wakuGossipSub(
init: Partial<RelayCreateOptions> = {} init: Partial<RelayCreateOptions> = {}
): (components: GossipSubComponents) => GossipSub { ): (components: GossipSubComponents) => GossipSub {

View File

@ -29,20 +29,30 @@ import { buildConfig } from "./utils.js";
const log = new Logger("sdk:filter"); const log = new Logger("sdk:filter");
class Filter implements IFilter { type FilterConstructorParams = {
connectionManager: ConnectionManager;
libp2p: Libp2p;
peerManager: PeerManager;
lightPush?: ILightPush;
options?: Partial<FilterProtocolOptions>;
};
export class Filter implements IFilter {
public readonly protocol: FilterCore; public readonly protocol: FilterCore;
private readonly config: FilterProtocolOptions; private readonly config: FilterProtocolOptions;
private connectionManager: ConnectionManager;
private libp2p: Libp2p;
private peerManager: PeerManager;
private lightPush?: ILightPush;
private activeSubscriptions = new Map<string, Subscription>(); private activeSubscriptions = new Map<string, Subscription>();
public constructor( public constructor(params: FilterConstructorParams) {
private connectionManager: ConnectionManager, this.config = buildConfig(params.options);
private libp2p: Libp2p, this.lightPush = params.lightPush;
private peerManager: PeerManager, this.peerManager = params.peerManager;
private lightPush?: ILightPush, this.libp2p = params.libp2p;
config?: Partial<FilterProtocolOptions> this.connectionManager = params.connectionManager;
) {
this.config = buildConfig(config);
this.protocol = new FilterCore( this.protocol = new FilterCore(
async (pubsubTopic, wakuMessage, peerIdStr) => { async (pubsubTopic, wakuMessage, peerIdStr) => {
@ -57,8 +67,8 @@ class Filter implements IFilter {
await subscription.processIncomingMessage(wakuMessage, peerIdStr); await subscription.processIncomingMessage(wakuMessage, peerIdStr);
}, },
connectionManager.pubsubTopics, params.connectionManager.pubsubTopics,
libp2p params.libp2p
); );
this.activeSubscriptions = new Map(); this.activeSubscriptions = new Map();
@ -281,13 +291,3 @@ class Filter implements IFilter {
return [...pubsubTopics]; return [...pubsubTopics];
} }
} }
export function wakuFilter(
connectionManager: ConnectionManager,
peerManager: PeerManager,
lightPush?: ILightPush,
config?: Partial<FilterProtocolOptions>
): (libp2p: Libp2p) => IFilter {
return (libp2p: Libp2p) =>
new Filter(connectionManager, libp2p, peerManager, lightPush, config);
}

View File

@ -1 +1 @@
export { wakuFilter } from "./filter.js"; export { Filter } from "./filter.js";

View File

@ -14,9 +14,9 @@ export {
defaultLibp2p, defaultLibp2p,
createLibp2pAndUpdateOptions createLibp2pAndUpdateOptions
} from "./create/index.js"; } from "./create/index.js";
export { wakuLightPush } from "./light_push/index.js"; export { LightPush } from "./light_push/index.js";
export { wakuFilter } from "./filter/index.js"; export { Filter } from "./filter/index.js";
export { wakuStore } from "./store/index.js"; export { Store } from "./store/index.js";
export * as waku from "@waku/core"; export * as waku from "@waku/core";
export * as utils from "@waku/utils"; export * as utils from "@waku/utils";

View File

@ -1 +1 @@
export { LightPush, wakuLightPush } from "./light_push.js"; export { LightPush } from "./light_push.js";

View File

@ -154,18 +154,18 @@ type MockLightPushOptions = {
}; };
function mockLightPush(options: MockLightPushOptions): LightPush { function mockLightPush(options: MockLightPushOptions): LightPush {
return new LightPush( return new LightPush({
{ connectionManager: {
pubsubTopics: options.pubsubTopics || [PUBSUB_TOPIC] pubsubTopics: options.pubsubTopics || [PUBSUB_TOPIC]
} as ConnectionManager, } as ConnectionManager,
{ peerManager: {
getPeers: () => getPeers: () =>
options.libp2p options.libp2p
.getPeers() .getPeers()
.slice(0, options.numPeersToUse || options.libp2p.getPeers().length) .slice(0, options.numPeersToUse || options.libp2p.getPeers().length)
} as unknown as PeerManager, } as unknown as PeerManager,
options.libp2p libp2p: options.libp2p
); });
} }
function mockPeer(id: string): Peer { function mockPeer(id: string): Peer {

View File

@ -25,15 +25,23 @@ const DEFAULT_SEND_OPTIONS: ISenderOptions = {
type RetryCallback = (peerId: PeerId) => Promise<CoreProtocolResult>; type RetryCallback = (peerId: PeerId) => Promise<CoreProtocolResult>;
type LightPushConstructorParams = {
connectionManager: ConnectionManager;
peerManager: PeerManager;
libp2p: Libp2p;
};
export class LightPush implements ILightPush { export class LightPush implements ILightPush {
private peerManager: PeerManager;
public readonly protocol: LightPushCore; public readonly protocol: LightPushCore;
public constructor( public constructor(params: LightPushConstructorParams) {
connectionManager: ConnectionManager, this.peerManager = params.peerManager;
private peerManager: PeerManager, this.protocol = new LightPushCore(
libp2p: Libp2p params.connectionManager.pubsubTopics,
) { params.libp2p
this.protocol = new LightPushCore(connectionManager.pubsubTopics, libp2p); );
} }
public async send( public async send(
@ -133,11 +141,3 @@ export class LightPush implements ILightPush {
} }
} }
} }
export function wakuLightPush(
connectionManager: ConnectionManager,
peerManager: PeerManager
): (libp2p: Libp2p) => ILightPush {
return (libp2p: Libp2p) =>
new LightPush(connectionManager, peerManager, libp2p);
}

View File

@ -1 +1 @@
export { Store, wakuStore } from "./store.js"; export { Store } from "./store.js";

View File

@ -16,20 +16,33 @@ import { PeerManager } from "../peer_manager/index.js";
const log = new Logger("waku:store:sdk"); const log = new Logger("waku:store:sdk");
type StoreConstructorParams = {
connectionManager: ConnectionManager;
libp2p: Libp2p;
peerManager: PeerManager;
options?: Partial<StoreProtocolOptions>;
};
/** /**
* StoreSDK is an implementation of the IStoreSDK interface. * StoreSDK is an implementation of the IStoreSDK interface.
* It provides methods to interact with the Waku Store protocol. * It provides methods to interact with the Waku Store protocol.
*/ */
export class Store implements IStore { export class Store implements IStore {
private options: Partial<StoreProtocolOptions>;
private peerManager: PeerManager;
private connectionManager: ConnectionManager;
public readonly protocol: StoreCore; public readonly protocol: StoreCore;
public constructor( public constructor(params: StoreConstructorParams) {
private connectionManager: ConnectionManager, this.options = params.options || {};
libp2p: Libp2p, this.peerManager = params.peerManager;
private peerManager: PeerManager, this.connectionManager = params.connectionManager;
private options?: Partial<StoreProtocolOptions>
) { this.protocol = new StoreCore(
this.protocol = new StoreCore(connectionManager.pubsubTopics, libp2p); params.connectionManager.pubsubTopics,
params.libp2p
);
} }
/** /**
@ -252,19 +265,3 @@ export class Store implements IStore {
return; return;
} }
} }
/**
* Factory function to create an instance of the StoreSDK.
*
* @param init - Partial options for protocol creation.
* @returns A function that takes a Libp2p instance and returns a StoreSDK instance.
*/
export function wakuStore(
connectionManager: ConnectionManager,
peerManager: PeerManager,
options?: Partial<StoreProtocolOptions>
): (libp2p: Libp2p) => IStore {
return (libp2p: Libp2p) => {
return new Store(connectionManager, libp2p, peerManager, options);
};
}

View File

@ -15,11 +15,11 @@ import type {
import { Protocols } from "@waku/interfaces"; import { Protocols } from "@waku/interfaces";
import { Logger } from "@waku/utils"; import { Logger } from "@waku/utils";
import { wakuFilter } from "../filter/index.js"; import { Filter } from "../filter/index.js";
import { HealthIndicator } from "../health_indicator/index.js"; import { HealthIndicator } from "../health_indicator/index.js";
import { wakuLightPush } from "../light_push/index.js"; import { LightPush } from "../light_push/index.js";
import { PeerManager } from "../peer_manager/index.js"; import { PeerManager } from "../peer_manager/index.js";
import { wakuStore } from "../store/index.js"; import { Store } from "../store/index.js";
import { waitForRemotePeer } from "./wait_for_remote_peer.js"; import { waitForRemotePeer } from "./wait_for_remote_peer.js";
@ -86,25 +86,32 @@ export class WakuNode implements IWaku {
}); });
} }
const store = wakuStore(this.connectionManager, this.peerManager, { this.store = new Store({
peer: options.store?.peer libp2p,
connectionManager: this.connectionManager,
peerManager: this.peerManager,
options: {
peer: options.store?.peer
}
}); });
this.store = store(libp2p);
} }
if (protocolsEnabled.lightpush) { if (protocolsEnabled.lightpush) {
const lightPush = wakuLightPush(this.connectionManager, this.peerManager); this.lightPush = new LightPush({
this.lightPush = lightPush(libp2p); libp2p,
peerManager: this.peerManager,
connectionManager: this.connectionManager
});
} }
if (protocolsEnabled.filter) { if (protocolsEnabled.filter) {
const filter = wakuFilter( this.filter = new Filter({
this.connectionManager, libp2p,
this.peerManager, connectionManager: this.connectionManager,
this.lightPush, peerManager: this.peerManager,
options.filter lightPush: this.lightPush,
); options: options.filter
this.filter = filter(libp2p); });
} }
log.info( log.info(