mirror of https://github.com/waku-org/js-waku.git
feat!: split outgoing and incoming message interface
While the data structure are similar, they serve different purposes. Having the same type has show to confuse API consumers Resolves #979
This commit is contained in:
parent
de6415f4f1
commit
8aa9b43f61
|
@ -4,6 +4,7 @@ import type { Peer } from "@libp2p/interface-peer-store";
|
|||
import type { IncomingStreamData } from "@libp2p/interface-registrar";
|
||||
import type {
|
||||
Callback,
|
||||
DecodedMessage,
|
||||
Decoder,
|
||||
Filter,
|
||||
Message,
|
||||
|
@ -77,7 +78,7 @@ export class WakuFilter implements Filter {
|
|||
* @param opts The FilterSubscriptionOpts used to narrow which messages are returned, and which peer to connect to.
|
||||
* @returns Unsubscribe function that can be used to end the subscription.
|
||||
*/
|
||||
async subscribe<T extends Message>(
|
||||
async subscribe<T extends DecodedMessage>(
|
||||
decoders: Decoder<T>[],
|
||||
callback: Callback<T>,
|
||||
opts?: ProtocolOptions
|
||||
|
@ -211,7 +212,7 @@ export class WakuFilter implements Filter {
|
|||
this.subscriptions.delete(requestId);
|
||||
}
|
||||
|
||||
private addDecoders<T extends Message>(
|
||||
private addDecoders<T extends DecodedMessage>(
|
||||
decoders: Map<string, Array<Decoder<T>>>
|
||||
): void {
|
||||
decoders.forEach((decoders, contentTopic) => {
|
||||
|
@ -224,7 +225,7 @@ export class WakuFilter implements Filter {
|
|||
});
|
||||
}
|
||||
|
||||
private deleteDecoders<T extends Message>(
|
||||
private deleteDecoders<T extends DecodedMessage>(
|
||||
decoders: Map<string, Array<Decoder<T>>>
|
||||
): void {
|
||||
decoders.forEach((decoders, contentTopic) => {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type {
|
||||
DecodedMessage,
|
||||
Decoder,
|
||||
Encoder,
|
||||
Message,
|
||||
|
@ -15,7 +16,7 @@ const OneMillion = BigInt(1_000_000);
|
|||
export const Version = 0;
|
||||
export { proto };
|
||||
|
||||
export class MessageV0 implements Message {
|
||||
export class MessageV0 implements DecodedMessage {
|
||||
constructor(protected proto: proto.WakuMessage) {}
|
||||
|
||||
get _rawPayload(): Uint8Array | undefined {
|
||||
|
@ -79,7 +80,7 @@ export class EncoderV0 implements Encoder {
|
|||
return {
|
||||
payload: message.payload,
|
||||
version: Version,
|
||||
contentTopic: message.contentTopic ?? this.contentTopic,
|
||||
contentTopic: this.contentTopic,
|
||||
timestamp: BigInt(timestamp.valueOf()) * OneMillion,
|
||||
rateLimitProof: message.rateLimitProof,
|
||||
};
|
||||
|
|
|
@ -16,6 +16,7 @@ import type {
|
|||
Relay,
|
||||
SendResult,
|
||||
} from "@waku/interfaces";
|
||||
import { DecodedMessage } from "@waku/interfaces";
|
||||
import debug from "debug";
|
||||
|
||||
import { DefaultPubSubTopic } from "../constants";
|
||||
|
@ -26,7 +27,7 @@ import * as constants from "./constants";
|
|||
|
||||
const log = debug("waku:relay");
|
||||
|
||||
export type Observer<T extends Message> = {
|
||||
export type Observer<T extends DecodedMessage> = {
|
||||
decoder: Decoder<T>;
|
||||
callback: Callback<T>;
|
||||
};
|
||||
|
@ -56,7 +57,7 @@ export type CreateOptions = {
|
|||
*/
|
||||
export class WakuRelay extends GossipSub implements Relay {
|
||||
pubSubTopic: string;
|
||||
defaultDecoder: Decoder<Message>;
|
||||
defaultDecoder: Decoder<DecodedMessage>;
|
||||
public static multicodec: string = constants.RelayCodecs[0];
|
||||
|
||||
/**
|
||||
|
@ -114,7 +115,7 @@ export class WakuRelay extends GossipSub implements Relay {
|
|||
*
|
||||
* @returns Function to delete the observer
|
||||
*/
|
||||
addObserver<T extends Message>(
|
||||
addObserver<T extends DecodedMessage>(
|
||||
decoder: Decoder<T>,
|
||||
callback: Callback<T>
|
||||
): () => void {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { Connection } from "@libp2p/interface-connection";
|
||||
import type { PeerId } from "@libp2p/interface-peer-id";
|
||||
import { Peer } from "@libp2p/interface-peer-store";
|
||||
import { Decoder, Message } from "@waku/interfaces";
|
||||
import { DecodedMessage, Decoder } from "@waku/interfaces";
|
||||
import debug from "debug";
|
||||
import all from "it-all";
|
||||
import * as lp from "it-length-prefixed";
|
||||
|
@ -106,7 +106,7 @@ export class WakuStore {
|
|||
* or if an error is encountered when processing the reply,
|
||||
* or if two decoders with the same content topic are passed.
|
||||
*/
|
||||
async queryOrderedCallback<T extends Message>(
|
||||
async queryOrderedCallback<T extends DecodedMessage>(
|
||||
decoders: Decoder<T>[],
|
||||
callback: (message: T) => Promise<void | boolean> | boolean | void,
|
||||
options?: QueryOptions
|
||||
|
@ -155,7 +155,7 @@ export class WakuStore {
|
|||
* or if an error is encountered when processing the reply,
|
||||
* or if two decoders with the same content topic are passed.
|
||||
*/
|
||||
async queryCallbackOnPromise<T extends Message>(
|
||||
async queryCallbackOnPromise<T extends DecodedMessage>(
|
||||
decoders: Decoder<T>[],
|
||||
callback: (
|
||||
message: Promise<T | undefined>
|
||||
|
@ -193,7 +193,7 @@ export class WakuStore {
|
|||
* or if an error is encountered when processing the reply,
|
||||
* or if two decoders with the same content topic are passed.
|
||||
*/
|
||||
async *queryGenerator<T extends Message>(
|
||||
async *queryGenerator<T extends DecodedMessage>(
|
||||
decoders: Decoder<T>[],
|
||||
options?: QueryOptions
|
||||
): AsyncGenerator<Promise<T | undefined>[]> {
|
||||
|
@ -266,7 +266,7 @@ export class WakuStore {
|
|||
}
|
||||
}
|
||||
|
||||
async function* paginate<T extends Message>(
|
||||
async function* paginate<T extends DecodedMessage>(
|
||||
connection: Connection,
|
||||
protocol: string,
|
||||
queryOpts: Params,
|
||||
|
|
|
@ -28,7 +28,7 @@ export type ProtocolOptions = {
|
|||
export type Callback<T extends Message> = (msg: T) => void | Promise<void>;
|
||||
|
||||
export interface Filter extends PointToPointProtocol {
|
||||
subscribe: <T extends Message>(
|
||||
subscribe: <T extends DecodedMessage>(
|
||||
decoders: Decoder<T>[],
|
||||
callback: Callback<T>,
|
||||
opts?: ProtocolOptions
|
||||
|
@ -38,7 +38,7 @@ export interface Filter extends PointToPointProtocol {
|
|||
export interface LightPush extends PointToPointProtocol {
|
||||
push: (
|
||||
encoder: Encoder,
|
||||
message: Partial<Message>,
|
||||
message: Message,
|
||||
opts?: ProtocolOptions
|
||||
) => Promise<SendResult>;
|
||||
}
|
||||
|
@ -76,27 +76,27 @@ export type StoreQueryOptions = {
|
|||
} & ProtocolOptions;
|
||||
|
||||
export interface Store extends PointToPointProtocol {
|
||||
queryOrderedCallback: <T extends Message>(
|
||||
queryOrderedCallback: <T extends DecodedMessage>(
|
||||
decoders: Decoder<T>[],
|
||||
callback: (message: T) => Promise<void | boolean> | boolean | void,
|
||||
options?: StoreQueryOptions
|
||||
) => Promise<void>;
|
||||
queryCallbackOnPromise: <T extends Message>(
|
||||
queryCallbackOnPromise: <T extends DecodedMessage>(
|
||||
decoders: Decoder<T>[],
|
||||
callback: (
|
||||
message: Promise<T | undefined>
|
||||
) => Promise<void | boolean> | boolean | void,
|
||||
options?: StoreQueryOptions
|
||||
) => Promise<void>;
|
||||
queryGenerator: <T extends Message>(
|
||||
queryGenerator: <T extends DecodedMessage>(
|
||||
decoders: Decoder<T>[],
|
||||
options?: StoreQueryOptions
|
||||
) => AsyncGenerator<Promise<T | undefined>[]>;
|
||||
}
|
||||
|
||||
export interface Relay extends GossipSub {
|
||||
send: (encoder: Encoder, message: Partial<Message>) => Promise<SendResult>;
|
||||
addObserver: <T extends Message>(
|
||||
send: (encoder: Encoder, message: Message) => Promise<SendResult>;
|
||||
addObserver: <T extends DecodedMessage>(
|
||||
decoder: Decoder<T>,
|
||||
callback: Callback<T>
|
||||
) => () => void;
|
||||
|
@ -155,6 +155,10 @@ export interface RateLimitProof {
|
|||
rlnIdentifier: Uint8Array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface matching the protobuf library.
|
||||
* Field types matches the protobuf type over the wire
|
||||
*/
|
||||
export interface ProtoMessage {
|
||||
payload: Uint8Array | undefined;
|
||||
contentTopic: string | undefined;
|
||||
|
@ -163,20 +167,29 @@ export interface ProtoMessage {
|
|||
rateLimitProof: RateLimitProof | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for messages to encode and send.
|
||||
*/
|
||||
export interface Message {
|
||||
payload?: Uint8Array;
|
||||
timestamp?: Date;
|
||||
rateLimitProof?: RateLimitProof;
|
||||
}
|
||||
|
||||
export interface Encoder {
|
||||
contentTopic: string;
|
||||
toWire: (message: Message) => Promise<Uint8Array | undefined>;
|
||||
toProtoObj: (message: Message) => Promise<ProtoMessage | undefined>;
|
||||
}
|
||||
|
||||
export interface DecodedMessage {
|
||||
payload: Uint8Array | undefined;
|
||||
contentTopic: string | undefined;
|
||||
timestamp: Date | undefined;
|
||||
rateLimitProof: RateLimitProof | undefined;
|
||||
}
|
||||
|
||||
export interface Encoder {
|
||||
contentTopic: string;
|
||||
toWire: (message: Partial<Message>) => Promise<Uint8Array | undefined>;
|
||||
toProtoObj: (message: Partial<Message>) => Promise<ProtoMessage | undefined>;
|
||||
}
|
||||
|
||||
export interface Decoder<T extends Message> {
|
||||
export interface Decoder<T extends DecodedMessage> {
|
||||
contentTopic: string;
|
||||
fromWireToProtoObj: (bytes: Uint8Array) => Promise<ProtoMessage | undefined>;
|
||||
fromProtoObj: (proto: ProtoMessage) => Promise<T | undefined>;
|
||||
|
|
|
@ -5,7 +5,13 @@ import {
|
|||
MessageV0,
|
||||
proto,
|
||||
} from "@waku/core/lib/waku_message/version_0";
|
||||
import type { Decoder, Encoder, Message, ProtoMessage } from "@waku/interfaces";
|
||||
import type {
|
||||
DecodedMessage,
|
||||
Decoder,
|
||||
Encoder,
|
||||
Message,
|
||||
ProtoMessage,
|
||||
} from "@waku/interfaces";
|
||||
import debug from "debug";
|
||||
|
||||
import { Symmetric } from "./constants.js";
|
||||
|
@ -38,7 +44,7 @@ export type Signature = {
|
|||
publicKey: Uint8Array | undefined;
|
||||
};
|
||||
|
||||
export class MessageV1 extends MessageV0 implements Message {
|
||||
export class MessageV1 extends MessageV0 implements DecodedMessage {
|
||||
private readonly _decodedPayload: Uint8Array;
|
||||
|
||||
constructor(
|
||||
|
|
|
@ -2,7 +2,7 @@ import { bytesToUtf8, utf8ToBytes } from "@waku/byte-utils";
|
|||
import { waitForRemotePeer } from "@waku/core/lib/wait_for_remote_peer";
|
||||
import { DecoderV0, EncoderV0 } from "@waku/core/lib/waku_message/version_0";
|
||||
import { createFullNode } from "@waku/create";
|
||||
import type { Message, WakuFull } from "@waku/interfaces";
|
||||
import type { DecodedMessage, WakuFull } from "@waku/interfaces";
|
||||
import { Protocols } from "@waku/interfaces";
|
||||
import { expect } from "chai";
|
||||
import debug from "debug";
|
||||
|
@ -47,7 +47,7 @@ describe("Waku Filter", () => {
|
|||
const messageText = "Filtering works!";
|
||||
const message = { payload: utf8ToBytes(messageText) };
|
||||
|
||||
const callback = (msg: Message): void => {
|
||||
const callback = (msg: DecodedMessage): void => {
|
||||
log("Got a message");
|
||||
messageCount++;
|
||||
expect(msg.contentTopic).to.eq(TestContentTopic);
|
||||
|
@ -71,7 +71,7 @@ describe("Waku Filter", () => {
|
|||
this.timeout(10000);
|
||||
|
||||
let messageCount = 0;
|
||||
const callback = (msg: Message): void => {
|
||||
const callback = (msg: DecodedMessage): void => {
|
||||
messageCount++;
|
||||
expect(msg.contentTopic).to.eq(TestContentTopic);
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
MessageV0,
|
||||
} from "@waku/core/lib/waku_message/version_0";
|
||||
import { createPrivacyNode } from "@waku/create";
|
||||
import type { Message, WakuPrivacy } from "@waku/interfaces";
|
||||
import type { DecodedMessage, WakuPrivacy } from "@waku/interfaces";
|
||||
import { Protocols } from "@waku/interfaces";
|
||||
import {
|
||||
AsymDecoder,
|
||||
|
@ -118,9 +118,11 @@ describe("Waku Relay [node only]", () => {
|
|||
timestamp: messageTimestamp,
|
||||
};
|
||||
|
||||
const receivedMsgPromise: Promise<Message> = new Promise((resolve) => {
|
||||
const receivedMsgPromise: Promise<DecodedMessage> = new Promise(
|
||||
(resolve) => {
|
||||
waku2.relay.addObserver(TestDecoder, resolve);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
await waku1.relay.send(TestEncoder, message);
|
||||
|
||||
|
@ -148,12 +150,12 @@ describe("Waku Relay [node only]", () => {
|
|||
const fooDecoder = new DecoderV0(fooContentTopic);
|
||||
const barDecoder = new DecoderV0(barContentTopic);
|
||||
|
||||
const fooMessages: Message[] = [];
|
||||
const fooMessages: DecodedMessage[] = [];
|
||||
waku2.relay.addObserver(fooDecoder, (msg) => {
|
||||
fooMessages.push(msg);
|
||||
});
|
||||
|
||||
const barMessages: Message[] = [];
|
||||
const barMessages: DecodedMessage[] = [];
|
||||
waku2.relay.addObserver(barDecoder, (msg) => {
|
||||
barMessages.push(msg);
|
||||
});
|
||||
|
@ -197,7 +199,7 @@ describe("Waku Relay [node only]", () => {
|
|||
const asymDecoder = new AsymDecoder(asymTopic, privateKey);
|
||||
const symDecoder = new SymDecoder(symTopic, symKey);
|
||||
|
||||
const msgs: Message[] = [];
|
||||
const msgs: DecodedMessage[] = [];
|
||||
waku2.relay.addObserver(asymDecoder, (wakuMsg) => {
|
||||
msgs.push(wakuMsg);
|
||||
});
|
||||
|
@ -228,7 +230,7 @@ describe("Waku Relay [node only]", () => {
|
|||
const contentTopic = "added-then-deleted-observer";
|
||||
|
||||
// The promise **fails** if we receive a message on this observer.
|
||||
const receivedMsgPromise: Promise<Message> = new Promise(
|
||||
const receivedMsgPromise: Promise<DecodedMessage> = new Promise(
|
||||
(resolve, reject) => {
|
||||
const deleteObserver = waku2.relay.addObserver(
|
||||
new DecoderV0(contentTopic),
|
||||
|
@ -304,7 +306,7 @@ describe("Waku Relay [node only]", () => {
|
|||
|
||||
const messageText = "Communicating using a custom pubsub topic";
|
||||
|
||||
const waku2ReceivedMsgPromise: Promise<Message> = new Promise(
|
||||
const waku2ReceivedMsgPromise: Promise<DecodedMessage> = new Promise(
|
||||
(resolve) => {
|
||||
waku2.relay.addObserver(TestDecoder, resolve);
|
||||
}
|
||||
|
@ -312,7 +314,7 @@ describe("Waku Relay [node only]", () => {
|
|||
|
||||
// The promise **fails** if we receive a message on the default
|
||||
// pubsub topic.
|
||||
const waku3NoMsgPromise: Promise<Message> = new Promise(
|
||||
const waku3NoMsgPromise: Promise<DecodedMessage> = new Promise(
|
||||
(resolve, reject) => {
|
||||
waku3.relay.addObserver(TestDecoder, reject);
|
||||
setTimeout(resolve, 1000);
|
||||
|
@ -466,7 +468,7 @@ describe("Waku Relay [node only]", () => {
|
|||
const msgStr = "Hello there!";
|
||||
const message = { payload: utf8ToBytes(msgStr) };
|
||||
|
||||
const waku2ReceivedMsgPromise: Promise<Message> = new Promise(
|
||||
const waku2ReceivedMsgPromise: Promise<DecodedMessage> = new Promise(
|
||||
(resolve) => {
|
||||
waku2.relay.addObserver(TestDecoder, resolve);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,12 @@ import { bytesToUtf8, utf8ToBytes } from "@waku/byte-utils";
|
|||
import { PeerDiscoveryStaticPeers } from "@waku/core/lib/peer_discovery_static_list";
|
||||
import { waitForRemotePeer } from "@waku/core/lib/wait_for_remote_peer";
|
||||
import { createLightNode, createPrivacyNode } from "@waku/create";
|
||||
import type { Message, Waku, WakuLight, WakuPrivacy } from "@waku/interfaces";
|
||||
import type {
|
||||
DecodedMessage,
|
||||
Waku,
|
||||
WakuLight,
|
||||
WakuPrivacy,
|
||||
} from "@waku/interfaces";
|
||||
import { Protocols } from "@waku/interfaces";
|
||||
import {
|
||||
generateSymmetricKey,
|
||||
|
@ -175,9 +180,11 @@ describe("Decryption Keys", () => {
|
|||
timestamp: messageTimestamp,
|
||||
};
|
||||
|
||||
const receivedMsgPromise: Promise<Message> = new Promise((resolve) => {
|
||||
const receivedMsgPromise: Promise<DecodedMessage> = new Promise(
|
||||
(resolve) => {
|
||||
waku2.relay.addObserver(decoder, resolve);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
await waku1.relay.send(encoder, message);
|
||||
|
||||
|
|
Loading…
Reference in New Issue