diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d8c5f0360..c01c0ce240 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Replaced `rlp` dependency with `@ethersproject/rlp`. -- **breaking**: `staticNoiseKey` changed from `Buffer` to `Uint8Array`. +- **Breaking**: `staticNoiseKey` changed from `Buffer` to `Uint8Array`. +- Implement Waku Store 2.0.0-beta4. The `WakuMessage.timestamp` field now stores nanoseconds over the wire. +- **Breaking**: `HistoryRPC.createQuery` takes `Date` instead of `number` for `startTime` and `endTime`. ### Removed diff --git a/buf.gen.yaml b/buf.gen.yaml index 40edf9635d..4bbd3ae240 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -3,4 +3,5 @@ version: v1beta1 plugins: - name: ts_proto out: ./src/proto - opt: grpc_js,esModuleInterop=true + strategy: all + opt: grpc_js,esModuleInterop=true,forceLong=long diff --git a/package.json b/package.json index 1c5f96b868..7fa920db06 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "examples:test": "run-s examples:pretest; for d in examples/*/; do (cd $d && npm test;); done", "proto": "run-s proto:*", "proto:lint": "buf lint", - "proto:build": "buf generate", + "proto:build": "rimraf ./src/proto && buf generate", "watch:build": "tsc -p tsconfig.json -w", "watch:test": "nyc --silent mocha --watch", "doc": "run-s doc:*", diff --git a/proto/waku/v2/message.proto b/proto/waku/v2/message.proto index bf3f78954f..6142752e9e 100644 --- a/proto/waku/v2/message.proto +++ b/proto/waku/v2/message.proto @@ -6,5 +6,6 @@ message WakuMessage { optional bytes payload = 1; optional string content_topic = 2; optional uint32 version = 3; - optional double timestamp = 4; + optional double timestamp_deprecated = 4; + optional sint64 timestamp = 10; } diff --git a/proto/waku/v2/store.proto b/proto/waku/v2/store/v2beta3/store.proto similarity index 96% rename from proto/waku/v2/store.proto rename to proto/waku/v2/store/v2beta3/store.proto index 7796348034..c2eb65e28e 100644 --- a/proto/waku/v2/store.proto +++ b/proto/waku/v2/store/v2beta3/store.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package waku.v2; +package waku.v2.store.v2beta3; import "waku/v2/message.proto"; diff --git a/proto/waku/v2/store/v2beta4/store.proto b/proto/waku/v2/store/v2beta4/store.proto new file mode 100644 index 0000000000..ea6b8cb546 --- /dev/null +++ b/proto/waku/v2/store/v2beta4/store.proto @@ -0,0 +1,49 @@ +syntax = "proto3"; + +package waku.v2.store.v2beta4; + +import "waku/v2/message.proto"; + +message Index { + bytes digest = 1; + sint64 received_time = 2; + sint64 sender_time = 3; +} + +message PagingInfo { + uint64 page_size = 1; + Index cursor = 2; + enum Direction { + DIRECTION_BACKWARD_UNSPECIFIED = 0; + DIRECTION_FORWARD = 1; + } + Direction direction = 3; +} + +message ContentFilter { + string content_topic = 1; +} + +message HistoryQuery { + optional string pub_sub_topic = 2; + repeated ContentFilter content_filters = 3; + optional PagingInfo paging_info = 4; + optional sint64 start_time = 5; + optional sint64 end_time = 6; +} + +message HistoryResponse { + repeated WakuMessage messages = 2; + PagingInfo paging_info = 3; + enum Error { + ERROR_NONE_UNSPECIFIED = 0; + ERROR_INVALID_CURSOR = 1; + } + Error error = 4; +} + +message HistoryRPC { + string request_id = 1; + HistoryQuery query = 2; + HistoryResponse response = 3; +} diff --git a/src/index.ts b/src/index.ts index e583056328..de67606bd1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,6 +30,4 @@ export * as waku_relay from "./lib/waku_relay"; export { WakuRelay, RelayCodecs } from "./lib/waku_relay"; export * as waku_store from "./lib/waku_store"; -export { PageDirection, WakuStore, StoreCodec } from "./lib/waku_store"; - -export * as proto from "./proto"; +export { PageDirection, WakuStore, StoreCodecs } from "./lib/waku_store"; diff --git a/src/lib/select_peer.ts b/src/lib/select_peer.ts index 0c85b8ba94..bf6f764308 100644 --- a/src/lib/select_peer.ts +++ b/src/lib/select_peer.ts @@ -24,10 +24,17 @@ export async function selectRandomPeer( */ export async function* getPeersForProtocol( libp2p: Libp2p, - protocol: string + protocols: string[] ): AsyncIterable { for await (const peer of libp2p.peerStore.getPeers()) { - if (!peer.protocols.includes(protocol)) { + let peerFound = false; + for (let i = 0; i < protocols.length; i++) { + if (peer.protocols.includes(protocols[i])) { + peerFound = true; + break; + } + } + if (!peerFound) { continue; } yield peer; diff --git a/src/lib/waku.ts b/src/lib/waku.ts index 248ac0df8a..3709a3ffa1 100644 --- a/src/lib/waku.ts +++ b/src/lib/waku.ts @@ -21,7 +21,7 @@ import { LightPushCodec, WakuLightPush } from "./waku_light_push"; import { DecryptionMethod, WakuMessage } from "./waku_message"; import { RelayCodecs, WakuRelay } from "./waku_relay"; import { RelayPingContentTopic } from "./waku_relay/constants"; -import { StoreCodec, WakuStore } from "./waku_store"; +import { StoreCodecs, WakuStore } from "./waku_store"; const websocketsTransportKey = Websockets.prototype[Symbol.toStringTag]; @@ -246,7 +246,9 @@ export class Waku { RelayCodecs.forEach((codec) => codecs.push(codec)); } if (_protocols.includes(Protocols.Store)) { - codecs.push(StoreCodec); + for (const codec of Object.values(StoreCodecs)) { + codecs.push(codec); + } } if (_protocols.includes(Protocols.LightPush)) { codecs.push(LightPushCodec); @@ -364,9 +366,11 @@ export class Waku { this.libp2p.peerStore.on( "change:protocols", ({ protocols: connectedPeerProtocols }) => { - if (connectedPeerProtocols.includes(StoreCodec)) { - dbg("Resolving for", StoreCodec, connectedPeerProtocols); - resolve(); + for (const codec of Object.values(StoreCodecs)) { + if (connectedPeerProtocols.includes(codec)) { + dbg("Resolving for", codec, connectedPeerProtocols); + resolve(); + } } } ); diff --git a/src/lib/waku_light_push/index.ts b/src/lib/waku_light_push/index.ts index b1a41b32de..684ff9dc40 100644 --- a/src/lib/waku_light_push/index.ts +++ b/src/lib/waku_light_push/index.ts @@ -100,7 +100,7 @@ export class WakuLightPush { * light push protocol. Waku may or may not be currently connected to these peers. */ get peers(): AsyncIterable { - return getPeersForProtocol(this.libp2p, LightPushCodec); + return getPeersForProtocol(this.libp2p, [LightPushCodec]); } /** diff --git a/src/lib/waku_message/index.ts b/src/lib/waku_message/index.ts index b18855f6c2..fa7b56902e 100644 --- a/src/lib/waku_message/index.ts +++ b/src/lib/waku_message/index.ts @@ -1,7 +1,7 @@ import debug from "debug"; +import Long from "long"; import { Reader } from "protobufjs/minimal"; -// Protecting the user from protobuf oddities import * as proto from "../../proto/waku/v2/message"; import { bytesToUtf8, utf8ToBytes } from "../utf8"; @@ -103,7 +103,9 @@ export class WakuMessage { return new WakuMessage( { payload: _payload, - timestamp: timestamp.valueOf() / 1000, + timestampDeprecated: timestamp.valueOf() / 1000, + // nanoseconds https://rfc.vac.dev/spec/14/ + timestamp: Long.fromNumber(timestamp.valueOf()).mul(1000), version, contentTopic, }, @@ -270,8 +272,20 @@ export class WakuMessage { } get timestamp(): Date | undefined { - if (this.proto.timestamp) { - return new Date(this.proto.timestamp * 1000); + // In the case we receive a value that is bigger than JS's max number, + // we catch the error and return undefined. + try { + if (this.proto.timestamp) { + // nanoseconds https://rfc.vac.dev/spec/14/ + const timestamp = this.proto.timestamp.div(1000).toNumber(); + return new Date(timestamp); + } + + if (this.proto.timestampDeprecated) { + return new Date(this.proto.timestampDeprecated * 1000); + } + } catch (e) { + return; } return; } diff --git a/src/lib/waku_store/history_rpc.ts b/src/lib/waku_store/history_rpc.ts index d1c596e9fb..fcf5b2fe98 100644 --- a/src/lib/waku_store/history_rpc.ts +++ b/src/lib/waku_store/history_rpc.ts @@ -1,7 +1,11 @@ +import Long from "long"; import { Reader } from "protobufjs/minimal"; import { v4 as uuid } from "uuid"; -import * as proto from "../../proto/waku/v2/store"; +import * as protoV2Beta3 from "../../proto/waku/v2/store/v2beta3/store"; +import * as protoV2Beta4 from "../../proto/waku/v2/store/v2beta4/store"; + +import { StoreCodecs } from "./index"; export enum PageDirection { BACKWARD = "backward", @@ -13,69 +17,142 @@ export interface Params { pubSubTopic: string; pageDirection: PageDirection; pageSize: number; - startTime?: number; - endTime?: number; - cursor?: proto.Index; + startTime?: Date; + endTime?: Date; + cursor?: protoV2Beta3.Index | protoV2Beta4.Index; + storeCodec?: StoreCodecs; } export class HistoryRPC { - public constructor(public proto: proto.HistoryRPC) {} + private readonly protoCodec: any; + + private constructor( + public readonly proto: protoV2Beta3.HistoryRPC | protoV2Beta4.HistoryRPC, + public readonly storeCodec: StoreCodecs + ) { + switch (storeCodec) { + case StoreCodecs.V2Beta3: + this.protoCodec = protoV2Beta3; + break; + case StoreCodecs.V2Beta4: + this.protoCodec = protoV2Beta4; + break; + default: + throw `Internal Error: Unexpected store codec value received in constructor: ${storeCodec}`; + } + } + + get query(): + | protoV2Beta3.HistoryQuery + | protoV2Beta4.HistoryQuery + | undefined { + return this.proto.query; + } + + get response(): + | protoV2Beta3.HistoryResponse + | protoV2Beta4.HistoryResponse + | undefined { + return this.proto.response; + } /** * Create History Query. */ static createQuery(params: Params): HistoryRPC { - const direction = directionToProto(params.pageDirection); - const pagingInfo = { - pageSize: params.pageSize, - cursor: params.cursor, - direction, - }; + const storeCodec = params.storeCodec ?? StoreCodecs.V2Beta4; const contentFilters = params.contentTopics.map((contentTopic) => { return { contentTopic }; }); - return new HistoryRPC({ - requestId: uuid(), - query: { - pubSubTopic: params.pubSubTopic, - contentFilters, - pagingInfo, - startTime: params.startTime, - endTime: params.endTime, - }, - response: undefined, - }); + const direction = directionToProto(params.pageDirection); + + switch (storeCodec) { + case StoreCodecs.V2Beta3: + // Using function to scope variables + return ((): HistoryRPC => { + const pagingInfo = { + pageSize: Long.fromNumber(params.pageSize), + cursor: params.cursor, + direction, + } as protoV2Beta3.PagingInfo; + + let startTime, endTime; + if (params.startTime) startTime = params.startTime.valueOf() / 1000; + + if (params.endTime) endTime = params.endTime.valueOf() / 1000; + + return new HistoryRPC( + { + requestId: uuid(), + query: { + pubSubTopic: params.pubSubTopic, + contentFilters, + pagingInfo, + startTime, + endTime, + }, + response: undefined, + }, + storeCodec + ); + })(); + case StoreCodecs.V2Beta4: + return ((): HistoryRPC => { + const pagingInfo = { + pageSize: Long.fromNumber(params.pageSize), + cursor: params.cursor, + direction, + } as protoV2Beta4.PagingInfo; + + let startTime, endTime; + if (params.startTime) + startTime = Long.fromNumber(params.startTime.valueOf()).mul(1000); + + if (params.endTime) + endTime = Long.fromNumber(params.endTime.valueOf()).mul(1000); + + return new HistoryRPC( + { + requestId: uuid(), + query: { + pubSubTopic: params.pubSubTopic, + contentFilters, + pagingInfo, + startTime, + endTime, + }, + response: undefined, + }, + storeCodec + ); + })(); + + default: + throw `Internal Error: Unexpected store codec value received in createQuery: ${storeCodec}`; + } } - static decode(bytes: Uint8Array): HistoryRPC { - const res = proto.HistoryRPC.decode(Reader.create(bytes)); - return new HistoryRPC(res); + decode(bytes: Uint8Array): HistoryRPC { + const res = this.protoCodec.HistoryRPC.decode(Reader.create(bytes)); + return new HistoryRPC(res, this.storeCodec); } encode(): Uint8Array { - return proto.HistoryRPC.encode(this.proto).finish(); - } - - get query(): proto.HistoryQuery | undefined { - return this.proto.query; - } - - get response(): proto.HistoryResponse | undefined { - return this.proto.response; + return this.protoCodec.HistoryRPC.encode(this.proto).finish(); } } function directionToProto( pageDirection: PageDirection -): proto.PagingInfo_Direction { +): protoV2Beta4.PagingInfo_Direction { switch (pageDirection) { case PageDirection.BACKWARD: - return proto.PagingInfo_Direction.DIRECTION_BACKWARD_UNSPECIFIED; + return protoV2Beta4.PagingInfo_Direction.DIRECTION_BACKWARD_UNSPECIFIED; case PageDirection.FORWARD: - return proto.PagingInfo_Direction.DIRECTION_FORWARD; + return protoV2Beta4.PagingInfo_Direction.DIRECTION_FORWARD; default: - return proto.PagingInfo_Direction.DIRECTION_BACKWARD_UNSPECIFIED; + return protoV2Beta4.PagingInfo_Direction.DIRECTION_BACKWARD_UNSPECIFIED; } } diff --git a/src/lib/waku_store/index.ts b/src/lib/waku_store/index.ts index fa0435b4b8..87a66e6ed6 100644 --- a/src/lib/waku_store/index.ts +++ b/src/lib/waku_store/index.ts @@ -6,7 +6,6 @@ import Libp2p from "libp2p"; import { Peer } from "libp2p/src/peer-store"; import PeerId from "peer-id"; -import { HistoryResponse_Error } from "../../proto"; import { getPeersForProtocol, selectRandomPeer } from "../select_peer"; import { hexToBytes } from "../utils"; import { DefaultPubSubTopic } from "../waku"; @@ -16,7 +15,10 @@ import { HistoryRPC, PageDirection } from "./history_rpc"; const dbg = debug("waku:store"); -export const StoreCodec = "/vac/waku/store/2.0.0-beta3"; +export enum StoreCodecs { + V2Beta3 = "/vac/waku/store/2.0.0-beta3", + V2Beta4 = "/vac/waku/store/2.0.0-beta4", +} export const DefaultPageSize = 10; @@ -128,9 +130,10 @@ export class WakuStore { options?: QueryOptions ): Promise { let startTime, endTime; + if (options?.timeFilter) { - startTime = options.timeFilter.startTime.getTime() / 1000; - endTime = options.timeFilter.endTime.getTime() / 1000; + startTime = options.timeFilter.startTime; + endTime = options.timeFilter.endTime; } const opts = Object.assign( @@ -140,12 +143,9 @@ export class WakuStore { pageSize: DefaultPageSize, }, options, - { - startTime, - endTime, - }, - { contentTopics } + { contentTopics, startTime, endTime } ); + dbg("Querying history with the following options", { peerId: options?.peerId?.toB58String(), ...options, @@ -161,8 +161,19 @@ export class WakuStore { if (!peer) throw "Failed to find known peer that registers waku store protocol"; } - if (!peer.protocols.includes(StoreCodec)) + + let storeCodec = ""; + for (const codec of Object.values(StoreCodecs)) { + if (peer.protocols.includes(codec)) { + storeCodec = codec; + // Do not break as we want to keep the last value + } + } + dbg(`Use store codec ${storeCodec}`); + if (!storeCodec) throw `Peer does not register waku store protocol: ${peer.id.toB58String()}`; + + Object.assign(opts, { storeCodec }); const connection = this.libp2p.connectionManager.get(peer.id); if (!connection) throw "Failed to get a connection to the peer"; @@ -191,7 +202,7 @@ export class WakuStore { const messages: WakuMessage[] = []; let cursor = undefined; while (true) { - const { stream } = await connection.newStream(StoreCodec); + const { stream } = await connection.newStream(storeCodec); const queryOpts = Object.assign(opts, { cursor }); const historyRpcQuery = HistoryRPC.createQuery(queryOpts); dbg("Querying store peer", connection.remoteAddr.toString()); @@ -203,18 +214,15 @@ export class WakuStore { lp.decode(), concat ); - const reply = HistoryRPC.decode(res.slice()); + const reply = historyRpcQuery.decode(res.slice()); const response = reply.response; if (!response) { throw "History response misses response field"; } - if ( - response.error && - response.error === HistoryResponse_Error.ERROR_INVALID_CURSOR - ) { - throw "History response contains an Error: INVALID CURSOR"; + if (response.error) { + throw "History response contains an Error" + response.error; } if (!response.messages || !response.messages.length) { @@ -279,7 +287,7 @@ export class WakuStore { this.decryptionKeys.set(hexToBytes(key), options ?? {}); } - /** + /**cursorV2Beta4 * Delete a decryption key that was used to attempt decryption of messages * received in subsequent [[queryHistory]] calls. * @@ -294,7 +302,12 @@ export class WakuStore { * store protocol. Waku may or may not be currently connected to these peers. */ get peers(): AsyncIterable { - return getPeersForProtocol(this.libp2p, StoreCodec); + const codecs = []; + for (const codec of Object.values(StoreCodecs)) { + codecs.push(codec); + } + + return getPeersForProtocol(this.libp2p, codecs); } /** diff --git a/src/proto/index.ts b/src/proto/index.ts deleted file mode 100644 index dc627fe35b..0000000000 --- a/src/proto/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export { WakuMessage } from "./waku/v2/message"; - -export { - Index, - PagingInfo, - PagingInfo_Direction, - ContentFilter, - HistoryQuery, - HistoryResponse, - HistoryResponse_Error, - HistoryRPC, -} from "./waku/v2/store"; diff --git a/src/proto/waku/v2/light_push.ts b/src/proto/waku/v2/light_push.ts index 2f2f9256a3..7a7977c2b2 100644 --- a/src/proto/waku/v2/light_push.ts +++ b/src/proto/waku/v2/light_push.ts @@ -253,6 +253,8 @@ type Builtin = export type DeepPartial = T extends Builtin ? T + : T extends Long + ? string | number | Long : T extends Array ? Array> : T extends ReadonlyArray diff --git a/src/proto/waku/v2/message.ts b/src/proto/waku/v2/message.ts index 76701b8505..c60ae7528a 100644 --- a/src/proto/waku/v2/message.ts +++ b/src/proto/waku/v2/message.ts @@ -8,7 +8,8 @@ export interface WakuMessage { payload?: Uint8Array | undefined; contentTopic?: string | undefined; version?: number | undefined; - timestamp?: number | undefined; + timestampDeprecated?: number | undefined; + timestamp?: Long | undefined; } function createBaseWakuMessage(): WakuMessage { @@ -16,6 +17,7 @@ function createBaseWakuMessage(): WakuMessage { payload: undefined, contentTopic: undefined, version: undefined, + timestampDeprecated: undefined, timestamp: undefined, }; } @@ -34,8 +36,11 @@ export const WakuMessage = { if (message.version !== undefined) { writer.uint32(24).uint32(message.version); } + if (message.timestampDeprecated !== undefined) { + writer.uint32(33).double(message.timestampDeprecated); + } if (message.timestamp !== undefined) { - writer.uint32(33).double(message.timestamp); + writer.uint32(80).sint64(message.timestamp); } return writer; }, @@ -57,7 +62,10 @@ export const WakuMessage = { message.version = reader.uint32(); break; case 4: - message.timestamp = reader.double(); + message.timestampDeprecated = reader.double(); + break; + case 10: + message.timestamp = reader.sint64() as Long; break; default: reader.skipType(tag & 7); @@ -76,7 +84,12 @@ export const WakuMessage = { ? String(object.contentTopic) : undefined, version: isSet(object.version) ? Number(object.version) : undefined, - timestamp: isSet(object.timestamp) ? Number(object.timestamp) : undefined, + timestampDeprecated: isSet(object.timestampDeprecated) + ? Number(object.timestampDeprecated) + : undefined, + timestamp: isSet(object.timestamp) + ? Long.fromString(object.timestamp) + : undefined, }; }, @@ -91,7 +104,10 @@ export const WakuMessage = { (obj.contentTopic = message.contentTopic); message.version !== undefined && (obj.version = Math.round(message.version)); - message.timestamp !== undefined && (obj.timestamp = message.timestamp); + message.timestampDeprecated !== undefined && + (obj.timestampDeprecated = message.timestampDeprecated); + message.timestamp !== undefined && + (obj.timestamp = (message.timestamp || undefined).toString()); return obj; }, @@ -102,7 +118,11 @@ export const WakuMessage = { message.payload = object.payload ?? undefined; message.contentTopic = object.contentTopic ?? undefined; message.version = object.version ?? undefined; - message.timestamp = object.timestamp ?? undefined; + message.timestampDeprecated = object.timestampDeprecated ?? undefined; + message.timestamp = + object.timestamp !== undefined && object.timestamp !== null + ? Long.fromValue(object.timestamp) + : undefined; return message; }, }; @@ -152,6 +172,8 @@ type Builtin = export type DeepPartial = T extends Builtin ? T + : T extends Long + ? string | number | Long : T extends Array ? Array> : T extends ReadonlyArray diff --git a/src/proto/waku/v2/store.ts b/src/proto/waku/v2/store/v2beta3/store.ts similarity index 96% rename from src/proto/waku/v2/store.ts rename to src/proto/waku/v2/store/v2beta3/store.ts index 8fff02f170..5dfda93966 100644 --- a/src/proto/waku/v2/store.ts +++ b/src/proto/waku/v2/store/v2beta3/store.ts @@ -1,9 +1,9 @@ /* eslint-disable */ import Long from "long"; import _m0 from "protobufjs/minimal"; -import { WakuMessage } from "../../waku/v2/message"; +import { WakuMessage } from "../../../../waku/v2/message"; -export const protobufPackage = "waku.v2"; +export const protobufPackage = "waku.v2.store.v2beta3"; export interface Index { digest: Uint8Array; @@ -12,7 +12,7 @@ export interface Index { } export interface PagingInfo { - pageSize: number; + pageSize: Long; cursor: Index | undefined; direction: PagingInfo_Direction; } @@ -189,7 +189,7 @@ export const Index = { }; function createBasePagingInfo(): PagingInfo { - return { pageSize: 0, cursor: undefined, direction: 0 }; + return { pageSize: Long.UZERO, cursor: undefined, direction: 0 }; } export const PagingInfo = { @@ -197,7 +197,7 @@ export const PagingInfo = { message: PagingInfo, writer: _m0.Writer = _m0.Writer.create() ): _m0.Writer { - if (message.pageSize !== 0) { + if (!message.pageSize.isZero()) { writer.uint32(8).uint64(message.pageSize); } if (message.cursor !== undefined) { @@ -217,7 +217,7 @@ export const PagingInfo = { const tag = reader.uint32(); switch (tag >>> 3) { case 1: - message.pageSize = longToNumber(reader.uint64() as Long); + message.pageSize = reader.uint64() as Long; break; case 2: message.cursor = Index.decode(reader, reader.uint32()); @@ -235,7 +235,9 @@ export const PagingInfo = { fromJSON(object: any): PagingInfo { return { - pageSize: isSet(object.pageSize) ? Number(object.pageSize) : 0, + pageSize: isSet(object.pageSize) + ? Long.fromString(object.pageSize) + : Long.UZERO, cursor: isSet(object.cursor) ? Index.fromJSON(object.cursor) : undefined, direction: isSet(object.direction) ? pagingInfo_DirectionFromJSON(object.direction) @@ -246,7 +248,7 @@ export const PagingInfo = { toJSON(message: PagingInfo): unknown { const obj: any = {}; message.pageSize !== undefined && - (obj.pageSize = Math.round(message.pageSize)); + (obj.pageSize = (message.pageSize || Long.UZERO).toString()); message.cursor !== undefined && (obj.cursor = message.cursor ? Index.toJSON(message.cursor) : undefined); message.direction !== undefined && @@ -258,7 +260,10 @@ export const PagingInfo = { object: I ): PagingInfo { const message = createBasePagingInfo(); - message.pageSize = object.pageSize ?? 0; + message.pageSize = + object.pageSize !== undefined && object.pageSize !== null + ? Long.fromValue(object.pageSize) + : Long.UZERO; message.cursor = object.cursor !== undefined && object.cursor !== null ? Index.fromPartial(object.cursor) @@ -671,6 +676,8 @@ type Builtin = export type DeepPartial = T extends Builtin ? T + : T extends Long + ? string | number | Long : T extends Array ? Array> : T extends ReadonlyArray @@ -687,13 +694,6 @@ export type Exact = P extends Builtin never >; -function longToNumber(long: Long): number { - if (long.gt(Number.MAX_SAFE_INTEGER)) { - throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); - } - return long.toNumber(); -} - if (_m0.util.Long !== Long) { _m0.util.Long = Long as any; _m0.configure(); diff --git a/src/proto/waku/v2/store/v2beta4/store.ts b/src/proto/waku/v2/store/v2beta4/store.ts new file mode 100644 index 0000000000..628a2d7bf9 --- /dev/null +++ b/src/proto/waku/v2/store/v2beta4/store.ts @@ -0,0 +1,729 @@ +/* eslint-disable */ +import Long from "long"; +import _m0 from "protobufjs/minimal"; +import { WakuMessage } from "../../../../waku/v2/message"; + +export const protobufPackage = "waku.v2.store.v2beta4"; + +export interface Index { + digest: Uint8Array; + receivedTime: Long; + senderTime: Long; +} + +export interface PagingInfo { + pageSize: Long; + cursor: Index | undefined; + direction: PagingInfo_Direction; +} + +export enum PagingInfo_Direction { + DIRECTION_BACKWARD_UNSPECIFIED = 0, + DIRECTION_FORWARD = 1, + UNRECOGNIZED = -1, +} + +export function pagingInfo_DirectionFromJSON( + object: any +): PagingInfo_Direction { + switch (object) { + case 0: + case "DIRECTION_BACKWARD_UNSPECIFIED": + return PagingInfo_Direction.DIRECTION_BACKWARD_UNSPECIFIED; + case 1: + case "DIRECTION_FORWARD": + return PagingInfo_Direction.DIRECTION_FORWARD; + case -1: + case "UNRECOGNIZED": + default: + return PagingInfo_Direction.UNRECOGNIZED; + } +} + +export function pagingInfo_DirectionToJSON( + object: PagingInfo_Direction +): string { + switch (object) { + case PagingInfo_Direction.DIRECTION_BACKWARD_UNSPECIFIED: + return "DIRECTION_BACKWARD_UNSPECIFIED"; + case PagingInfo_Direction.DIRECTION_FORWARD: + return "DIRECTION_FORWARD"; + default: + return "UNKNOWN"; + } +} + +export interface ContentFilter { + contentTopic: string; +} + +export interface HistoryQuery { + pubSubTopic?: string | undefined; + contentFilters: ContentFilter[]; + pagingInfo?: PagingInfo | undefined; + startTime?: Long | undefined; + endTime?: Long | undefined; +} + +export interface HistoryResponse { + messages: WakuMessage[]; + pagingInfo: PagingInfo | undefined; + error: HistoryResponse_Error; +} + +export enum HistoryResponse_Error { + ERROR_NONE_UNSPECIFIED = 0, + ERROR_INVALID_CURSOR = 1, + UNRECOGNIZED = -1, +} + +export function historyResponse_ErrorFromJSON( + object: any +): HistoryResponse_Error { + switch (object) { + case 0: + case "ERROR_NONE_UNSPECIFIED": + return HistoryResponse_Error.ERROR_NONE_UNSPECIFIED; + case 1: + case "ERROR_INVALID_CURSOR": + return HistoryResponse_Error.ERROR_INVALID_CURSOR; + case -1: + case "UNRECOGNIZED": + default: + return HistoryResponse_Error.UNRECOGNIZED; + } +} + +export function historyResponse_ErrorToJSON( + object: HistoryResponse_Error +): string { + switch (object) { + case HistoryResponse_Error.ERROR_NONE_UNSPECIFIED: + return "ERROR_NONE_UNSPECIFIED"; + case HistoryResponse_Error.ERROR_INVALID_CURSOR: + return "ERROR_INVALID_CURSOR"; + default: + return "UNKNOWN"; + } +} + +export interface HistoryRPC { + requestId: string; + query: HistoryQuery | undefined; + response: HistoryResponse | undefined; +} + +function createBaseIndex(): Index { + return { + digest: new Uint8Array(), + receivedTime: Long.ZERO, + senderTime: Long.ZERO, + }; +} + +export const Index = { + encode(message: Index, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.digest.length !== 0) { + writer.uint32(10).bytes(message.digest); + } + if (!message.receivedTime.isZero()) { + writer.uint32(16).sint64(message.receivedTime); + } + if (!message.senderTime.isZero()) { + writer.uint32(24).sint64(message.senderTime); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Index { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseIndex(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.digest = reader.bytes(); + break; + case 2: + message.receivedTime = reader.sint64() as Long; + break; + case 3: + message.senderTime = reader.sint64() as Long; + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Index { + return { + digest: isSet(object.digest) + ? bytesFromBase64(object.digest) + : new Uint8Array(), + receivedTime: isSet(object.receivedTime) + ? Long.fromString(object.receivedTime) + : Long.ZERO, + senderTime: isSet(object.senderTime) + ? Long.fromString(object.senderTime) + : Long.ZERO, + }; + }, + + toJSON(message: Index): unknown { + const obj: any = {}; + message.digest !== undefined && + (obj.digest = base64FromBytes( + message.digest !== undefined ? message.digest : new Uint8Array() + )); + message.receivedTime !== undefined && + (obj.receivedTime = (message.receivedTime || Long.ZERO).toString()); + message.senderTime !== undefined && + (obj.senderTime = (message.senderTime || Long.ZERO).toString()); + return obj; + }, + + fromPartial, I>>(object: I): Index { + const message = createBaseIndex(); + message.digest = object.digest ?? new Uint8Array(); + message.receivedTime = + object.receivedTime !== undefined && object.receivedTime !== null + ? Long.fromValue(object.receivedTime) + : Long.ZERO; + message.senderTime = + object.senderTime !== undefined && object.senderTime !== null + ? Long.fromValue(object.senderTime) + : Long.ZERO; + return message; + }, +}; + +function createBasePagingInfo(): PagingInfo { + return { pageSize: Long.UZERO, cursor: undefined, direction: 0 }; +} + +export const PagingInfo = { + encode( + message: PagingInfo, + writer: _m0.Writer = _m0.Writer.create() + ): _m0.Writer { + if (!message.pageSize.isZero()) { + writer.uint32(8).uint64(message.pageSize); + } + if (message.cursor !== undefined) { + Index.encode(message.cursor, writer.uint32(18).fork()).ldelim(); + } + if (message.direction !== 0) { + writer.uint32(24).int32(message.direction); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): PagingInfo { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePagingInfo(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.pageSize = reader.uint64() as Long; + break; + case 2: + message.cursor = Index.decode(reader, reader.uint32()); + break; + case 3: + message.direction = reader.int32() as any; + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): PagingInfo { + return { + pageSize: isSet(object.pageSize) + ? Long.fromString(object.pageSize) + : Long.UZERO, + cursor: isSet(object.cursor) ? Index.fromJSON(object.cursor) : undefined, + direction: isSet(object.direction) + ? pagingInfo_DirectionFromJSON(object.direction) + : 0, + }; + }, + + toJSON(message: PagingInfo): unknown { + const obj: any = {}; + message.pageSize !== undefined && + (obj.pageSize = (message.pageSize || Long.UZERO).toString()); + message.cursor !== undefined && + (obj.cursor = message.cursor ? Index.toJSON(message.cursor) : undefined); + message.direction !== undefined && + (obj.direction = pagingInfo_DirectionToJSON(message.direction)); + return obj; + }, + + fromPartial, I>>( + object: I + ): PagingInfo { + const message = createBasePagingInfo(); + message.pageSize = + object.pageSize !== undefined && object.pageSize !== null + ? Long.fromValue(object.pageSize) + : Long.UZERO; + message.cursor = + object.cursor !== undefined && object.cursor !== null + ? Index.fromPartial(object.cursor) + : undefined; + message.direction = object.direction ?? 0; + return message; + }, +}; + +function createBaseContentFilter(): ContentFilter { + return { contentTopic: "" }; +} + +export const ContentFilter = { + encode( + message: ContentFilter, + writer: _m0.Writer = _m0.Writer.create() + ): _m0.Writer { + if (message.contentTopic !== "") { + writer.uint32(10).string(message.contentTopic); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): ContentFilter { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseContentFilter(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.contentTopic = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): ContentFilter { + return { + contentTopic: isSet(object.contentTopic) + ? String(object.contentTopic) + : "", + }; + }, + + toJSON(message: ContentFilter): unknown { + const obj: any = {}; + message.contentTopic !== undefined && + (obj.contentTopic = message.contentTopic); + return obj; + }, + + fromPartial, I>>( + object: I + ): ContentFilter { + const message = createBaseContentFilter(); + message.contentTopic = object.contentTopic ?? ""; + return message; + }, +}; + +function createBaseHistoryQuery(): HistoryQuery { + return { + pubSubTopic: undefined, + contentFilters: [], + pagingInfo: undefined, + startTime: undefined, + endTime: undefined, + }; +} + +export const HistoryQuery = { + encode( + message: HistoryQuery, + writer: _m0.Writer = _m0.Writer.create() + ): _m0.Writer { + if (message.pubSubTopic !== undefined) { + writer.uint32(18).string(message.pubSubTopic); + } + for (const v of message.contentFilters) { + ContentFilter.encode(v!, writer.uint32(26).fork()).ldelim(); + } + if (message.pagingInfo !== undefined) { + PagingInfo.encode(message.pagingInfo, writer.uint32(34).fork()).ldelim(); + } + if (message.startTime !== undefined) { + writer.uint32(40).sint64(message.startTime); + } + if (message.endTime !== undefined) { + writer.uint32(48).sint64(message.endTime); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): HistoryQuery { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseHistoryQuery(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 2: + message.pubSubTopic = reader.string(); + break; + case 3: + message.contentFilters.push( + ContentFilter.decode(reader, reader.uint32()) + ); + break; + case 4: + message.pagingInfo = PagingInfo.decode(reader, reader.uint32()); + break; + case 5: + message.startTime = reader.sint64() as Long; + break; + case 6: + message.endTime = reader.sint64() as Long; + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): HistoryQuery { + return { + pubSubTopic: isSet(object.pubSubTopic) + ? String(object.pubSubTopic) + : undefined, + contentFilters: Array.isArray(object?.contentFilters) + ? object.contentFilters.map((e: any) => ContentFilter.fromJSON(e)) + : [], + pagingInfo: isSet(object.pagingInfo) + ? PagingInfo.fromJSON(object.pagingInfo) + : undefined, + startTime: isSet(object.startTime) + ? Long.fromString(object.startTime) + : undefined, + endTime: isSet(object.endTime) + ? Long.fromString(object.endTime) + : undefined, + }; + }, + + toJSON(message: HistoryQuery): unknown { + const obj: any = {}; + message.pubSubTopic !== undefined && + (obj.pubSubTopic = message.pubSubTopic); + if (message.contentFilters) { + obj.contentFilters = message.contentFilters.map((e) => + e ? ContentFilter.toJSON(e) : undefined + ); + } else { + obj.contentFilters = []; + } + message.pagingInfo !== undefined && + (obj.pagingInfo = message.pagingInfo + ? PagingInfo.toJSON(message.pagingInfo) + : undefined); + message.startTime !== undefined && + (obj.startTime = (message.startTime || undefined).toString()); + message.endTime !== undefined && + (obj.endTime = (message.endTime || undefined).toString()); + return obj; + }, + + fromPartial, I>>( + object: I + ): HistoryQuery { + const message = createBaseHistoryQuery(); + message.pubSubTopic = object.pubSubTopic ?? undefined; + message.contentFilters = + object.contentFilters?.map((e) => ContentFilter.fromPartial(e)) || []; + message.pagingInfo = + object.pagingInfo !== undefined && object.pagingInfo !== null + ? PagingInfo.fromPartial(object.pagingInfo) + : undefined; + message.startTime = + object.startTime !== undefined && object.startTime !== null + ? Long.fromValue(object.startTime) + : undefined; + message.endTime = + object.endTime !== undefined && object.endTime !== null + ? Long.fromValue(object.endTime) + : undefined; + return message; + }, +}; + +function createBaseHistoryResponse(): HistoryResponse { + return { messages: [], pagingInfo: undefined, error: 0 }; +} + +export const HistoryResponse = { + encode( + message: HistoryResponse, + writer: _m0.Writer = _m0.Writer.create() + ): _m0.Writer { + for (const v of message.messages) { + WakuMessage.encode(v!, writer.uint32(18).fork()).ldelim(); + } + if (message.pagingInfo !== undefined) { + PagingInfo.encode(message.pagingInfo, writer.uint32(26).fork()).ldelim(); + } + if (message.error !== 0) { + writer.uint32(32).int32(message.error); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): HistoryResponse { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseHistoryResponse(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 2: + message.messages.push(WakuMessage.decode(reader, reader.uint32())); + break; + case 3: + message.pagingInfo = PagingInfo.decode(reader, reader.uint32()); + break; + case 4: + message.error = reader.int32() as any; + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): HistoryResponse { + return { + messages: Array.isArray(object?.messages) + ? object.messages.map((e: any) => WakuMessage.fromJSON(e)) + : [], + pagingInfo: isSet(object.pagingInfo) + ? PagingInfo.fromJSON(object.pagingInfo) + : undefined, + error: isSet(object.error) + ? historyResponse_ErrorFromJSON(object.error) + : 0, + }; + }, + + toJSON(message: HistoryResponse): unknown { + const obj: any = {}; + if (message.messages) { + obj.messages = message.messages.map((e) => + e ? WakuMessage.toJSON(e) : undefined + ); + } else { + obj.messages = []; + } + message.pagingInfo !== undefined && + (obj.pagingInfo = message.pagingInfo + ? PagingInfo.toJSON(message.pagingInfo) + : undefined); + message.error !== undefined && + (obj.error = historyResponse_ErrorToJSON(message.error)); + return obj; + }, + + fromPartial, I>>( + object: I + ): HistoryResponse { + const message = createBaseHistoryResponse(); + message.messages = + object.messages?.map((e) => WakuMessage.fromPartial(e)) || []; + message.pagingInfo = + object.pagingInfo !== undefined && object.pagingInfo !== null + ? PagingInfo.fromPartial(object.pagingInfo) + : undefined; + message.error = object.error ?? 0; + return message; + }, +}; + +function createBaseHistoryRPC(): HistoryRPC { + return { requestId: "", query: undefined, response: undefined }; +} + +export const HistoryRPC = { + encode( + message: HistoryRPC, + writer: _m0.Writer = _m0.Writer.create() + ): _m0.Writer { + if (message.requestId !== "") { + writer.uint32(10).string(message.requestId); + } + if (message.query !== undefined) { + HistoryQuery.encode(message.query, writer.uint32(18).fork()).ldelim(); + } + if (message.response !== undefined) { + HistoryResponse.encode( + message.response, + writer.uint32(26).fork() + ).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): HistoryRPC { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseHistoryRPC(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.requestId = reader.string(); + break; + case 2: + message.query = HistoryQuery.decode(reader, reader.uint32()); + break; + case 3: + message.response = HistoryResponse.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): HistoryRPC { + return { + requestId: isSet(object.requestId) ? String(object.requestId) : "", + query: isSet(object.query) + ? HistoryQuery.fromJSON(object.query) + : undefined, + response: isSet(object.response) + ? HistoryResponse.fromJSON(object.response) + : undefined, + }; + }, + + toJSON(message: HistoryRPC): unknown { + const obj: any = {}; + message.requestId !== undefined && (obj.requestId = message.requestId); + message.query !== undefined && + (obj.query = message.query + ? HistoryQuery.toJSON(message.query) + : undefined); + message.response !== undefined && + (obj.response = message.response + ? HistoryResponse.toJSON(message.response) + : undefined); + return obj; + }, + + fromPartial, I>>( + object: I + ): HistoryRPC { + const message = createBaseHistoryRPC(); + message.requestId = object.requestId ?? ""; + message.query = + object.query !== undefined && object.query !== null + ? HistoryQuery.fromPartial(object.query) + : undefined; + message.response = + object.response !== undefined && object.response !== null + ? HistoryResponse.fromPartial(object.response) + : undefined; + return message; + }, +}; + +declare var self: any | undefined; +declare var window: any | undefined; +declare var global: any | undefined; +var globalThis: any = (() => { + if (typeof globalThis !== "undefined") return globalThis; + if (typeof self !== "undefined") return self; + if (typeof window !== "undefined") return window; + if (typeof global !== "undefined") return global; + throw "Unable to locate global object"; +})(); + +const atob: (b64: string) => string = + globalThis.atob || + ((b64) => globalThis.Buffer.from(b64, "base64").toString("binary")); +function bytesFromBase64(b64: string): Uint8Array { + const bin = atob(b64); + const arr = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; ++i) { + arr[i] = bin.charCodeAt(i); + } + return arr; +} + +const btoa: (bin: string) => string = + globalThis.btoa || + ((bin) => globalThis.Buffer.from(bin, "binary").toString("base64")); +function base64FromBytes(arr: Uint8Array): string { + const bin: string[] = []; + for (const byte of arr) { + bin.push(String.fromCharCode(byte)); + } + return btoa(bin.join("")); +} + +type Builtin = + | Date + | Function + | Uint8Array + | string + | number + | boolean + | undefined; + +export type DeepPartial = T extends Builtin + ? T + : T extends Long + ? string | number | Long + : T extends Array + ? Array> + : T extends ReadonlyArray + ? ReadonlyArray> + : T extends {} + ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin + ? P + : P & { [K in keyof P]: Exact } & Record< + Exclude>, + never + >; + +if (_m0.util.Long !== Long) { + _m0.util.Long = Long as any; + _m0.configure(); +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +}