@waku/core 0.0.31-08fc2d1.0 → 0.0.31-88a29c3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,3 @@
1
- import { proto_store as proto } from "@waku/proto";
2
1
  import { Logger } from "@waku/utils";
3
2
  import all from "it-all";
4
3
  import * as lp from "it-length-prefixed";
@@ -6,29 +5,24 @@ import { pipe } from "it-pipe";
6
5
  import { Uint8ArrayList } from "uint8arraylist";
7
6
  import { BaseProtocol } from "../base_protocol.js";
8
7
  import { toProtoMessage } from "../to_proto_message.js";
9
- import { HistoryRpc, PageDirection } from "./history_rpc.js";
10
- var HistoryError = proto.HistoryResponse.HistoryError;
8
+ import { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE, StoreQueryRequest, StoreQueryResponse } from "./rpc.js";
11
9
  const log = new Logger("store");
12
- export const StoreCodec = "/vac/waku/store/2.0.0-beta4";
13
- export { PageDirection };
14
- /**
15
- * Implements the [Waku v2 Store protocol](https://rfc.vac.dev/spec/13/).
16
- *
17
- * The Waku Store protocol can be used to retrieved historical messages.
18
- */
10
+ export const StoreCodec = "/vac/waku/store-query/3.0.0";
19
11
  export class StoreCore extends BaseProtocol {
20
12
  constructor(libp2p, options) {
21
- super(StoreCodec, libp2p.components, log, options.pubsubTopics, options);
13
+ super(StoreCodec, libp2p.components, log, options?.pubsubTopics || [], options);
22
14
  }
23
15
  async *queryPerPage(queryOpts, decoders, peer) {
24
16
  if (queryOpts.contentTopics.toString() !==
25
17
  Array.from(decoders.keys()).toString()) {
26
18
  throw new Error("Internal error, the decoders should match the query's content topics");
27
19
  }
28
- let currentCursor = queryOpts.cursor;
20
+ let currentCursor = queryOpts.paginationCursor;
29
21
  while (true) {
30
- queryOpts.cursor = currentCursor;
31
- const historyRpcQuery = HistoryRpc.createQuery(queryOpts);
22
+ const storeQueryRequest = StoreQueryRequest.create({
23
+ ...queryOpts,
24
+ paginationCursor: currentCursor
25
+ });
32
26
  let stream;
33
27
  try {
34
28
  stream = await this.getStream(peer);
@@ -37,50 +31,48 @@ export class StoreCore extends BaseProtocol {
37
31
  log.error("Failed to get stream", e);
38
32
  break;
39
33
  }
40
- const res = await pipe([historyRpcQuery.encode()], lp.encode, stream, lp.decode, async (source) => await all(source));
34
+ const res = await pipe([storeQueryRequest.encode()], lp.encode, stream, lp.decode, async (source) => await all(source));
41
35
  const bytes = new Uint8ArrayList();
42
36
  res.forEach((chunk) => {
43
37
  bytes.append(chunk);
44
38
  });
45
- const reply = historyRpcQuery.decode(bytes);
46
- if (!reply.response) {
47
- log.warn("Stopping pagination due to store `response` field missing");
48
- break;
49
- }
50
- const response = reply.response;
51
- if (response.error && response.error !== HistoryError.NONE) {
52
- throw "History response contains an Error: " + response.error;
39
+ const storeQueryResponse = StoreQueryResponse.decode(bytes);
40
+ if (!storeQueryResponse.statusCode ||
41
+ storeQueryResponse.statusCode >= 300) {
42
+ const errorMessage = `Store query failed with status code: ${storeQueryResponse.statusCode}, description: ${storeQueryResponse.statusDesc}`;
43
+ log.error(errorMessage);
44
+ throw new Error(errorMessage);
53
45
  }
54
- if (!response.messages || !response.messages.length) {
55
- log.warn("Stopping pagination due to store `response.messages` field missing or empty");
46
+ if (!storeQueryResponse.messages || !storeQueryResponse.messages.length) {
47
+ log.warn("Stopping pagination due to empty messages in response");
56
48
  break;
57
49
  }
58
- log.error(`${response.messages.length} messages retrieved from store`);
59
- yield response.messages.map((protoMsg) => {
60
- const contentTopic = protoMsg.contentTopic;
61
- if (typeof contentTopic !== "undefined") {
50
+ log.info(`${storeQueryResponse.messages.length} messages retrieved from store`);
51
+ const decodedMessages = storeQueryResponse.messages.map((protoMsg) => {
52
+ if (!protoMsg.message) {
53
+ return Promise.resolve(undefined);
54
+ }
55
+ const contentTopic = protoMsg.message.contentTopic;
56
+ if (contentTopic) {
62
57
  const decoder = decoders.get(contentTopic);
63
58
  if (decoder) {
64
- return decoder.fromProtoObj(queryOpts.pubsubTopic, toProtoMessage(protoMsg));
59
+ return decoder.fromProtoObj(protoMsg.pubsubTopic || "", toProtoMessage(protoMsg.message));
65
60
  }
66
61
  }
67
62
  return Promise.resolve(undefined);
68
63
  });
69
- const nextCursor = response.pagingInfo?.cursor;
70
- if (typeof nextCursor === "undefined") {
71
- // If the server does not return cursor then there is an issue,
72
- // Need to abort, or we end up in an infinite loop
73
- log.warn("Stopping pagination due to `response.pagingInfo.cursor` missing from store response");
74
- break;
64
+ yield decodedMessages;
65
+ if (queryOpts.paginationForward) {
66
+ currentCursor =
67
+ storeQueryResponse.messages[storeQueryResponse.messages.length - 1]
68
+ .messageHash;
69
+ }
70
+ else {
71
+ currentCursor = storeQueryResponse.messages[0].messageHash;
75
72
  }
76
- currentCursor = nextCursor;
77
- const responsePageSize = response.pagingInfo?.pageSize;
78
- const queryPageSize = historyRpcQuery.query?.pagingInfo?.pageSize;
79
- if (
80
- // Response page size smaller than query, meaning this is the last page
81
- responsePageSize &&
82
- queryPageSize &&
83
- responsePageSize < queryPageSize) {
73
+ if (storeQueryResponse.messages.length > MAX_PAGE_SIZE &&
74
+ storeQueryResponse.messages.length <
75
+ (queryOpts.paginationLimit || DEFAULT_PAGE_SIZE)) {
84
76
  break;
85
77
  }
86
78
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/store/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/store/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { QueryRequestParams } from "@waku/interfaces";
2
+ import { proto_store as proto } from "@waku/proto";
3
+ import type { Uint8ArrayList } from "uint8arraylist";
4
+ export declare const DEFAULT_PAGE_SIZE = 20;
5
+ export declare const MAX_PAGE_SIZE = 100;
6
+ export declare class StoreQueryRequest {
7
+ proto: proto.StoreQueryRequest;
8
+ constructor(proto: proto.StoreQueryRequest);
9
+ static create(params: QueryRequestParams): StoreQueryRequest;
10
+ static decode(bytes: Uint8ArrayList): StoreQueryRequest;
11
+ encode(): Uint8Array;
12
+ }
13
+ export declare class StoreQueryResponse {
14
+ proto: proto.StoreQueryResponse;
15
+ constructor(proto: proto.StoreQueryResponse);
16
+ static decode(bytes: Uint8ArrayList): StoreQueryResponse;
17
+ encode(): Uint8Array;
18
+ get statusCode(): number | undefined;
19
+ get statusDesc(): string | undefined;
20
+ get messages(): proto.WakuMessageKeyValue[];
21
+ get paginationCursor(): Uint8Array | undefined;
22
+ }
@@ -0,0 +1,74 @@
1
+ import { proto_store as proto } from "@waku/proto";
2
+ import { v4 as uuid } from "uuid";
3
+ // https://github.com/waku-org/nwaku/blob/7205f95cff9f49ca0bb762e8fd0bf56a6a7f3b3b/waku/waku_store/common.nim#L12
4
+ export const DEFAULT_PAGE_SIZE = 20;
5
+ export const MAX_PAGE_SIZE = 100;
6
+ const ONE_MILLION = 1_000000;
7
+ export class StoreQueryRequest {
8
+ proto;
9
+ constructor(proto) {
10
+ this.proto = proto;
11
+ }
12
+ static create(params) {
13
+ const request = new StoreQueryRequest({
14
+ ...params,
15
+ requestId: uuid(),
16
+ timeStart: params.timeStart
17
+ ? BigInt(params.timeStart.getTime() * ONE_MILLION)
18
+ : undefined,
19
+ timeEnd: params.timeEnd
20
+ ? BigInt(params.timeEnd.getTime() * ONE_MILLION)
21
+ : undefined,
22
+ messageHashes: params.messageHashes || [],
23
+ paginationLimit: params.paginationLimit
24
+ ? BigInt(params.paginationLimit)
25
+ : undefined
26
+ });
27
+ // Validate request parameters based on RFC
28
+ if ((params.pubsubTopic && !params.contentTopics) ||
29
+ (!params.pubsubTopic && params.contentTopics)) {
30
+ throw new Error("Both pubsubTopic and contentTopics must be set or unset");
31
+ }
32
+ if (params.messageHashes &&
33
+ (params.pubsubTopic ||
34
+ params.contentTopics ||
35
+ params.timeStart ||
36
+ params.timeEnd)) {
37
+ throw new Error("Message hash lookup queries cannot include content filter criteria");
38
+ }
39
+ return request;
40
+ }
41
+ static decode(bytes) {
42
+ const res = proto.StoreQueryRequest.decode(bytes);
43
+ return new StoreQueryRequest(res);
44
+ }
45
+ encode() {
46
+ return proto.StoreQueryRequest.encode(this.proto);
47
+ }
48
+ }
49
+ export class StoreQueryResponse {
50
+ proto;
51
+ constructor(proto) {
52
+ this.proto = proto;
53
+ }
54
+ static decode(bytes) {
55
+ const res = proto.StoreQueryResponse.decode(bytes);
56
+ return new StoreQueryResponse(res);
57
+ }
58
+ encode() {
59
+ return proto.StoreQueryResponse.encode(this.proto);
60
+ }
61
+ get statusCode() {
62
+ return this.proto.statusCode;
63
+ }
64
+ get statusDesc() {
65
+ return this.proto.statusDesc;
66
+ }
67
+ get messages() {
68
+ return this.proto.messages;
69
+ }
70
+ get paginationCursor() {
71
+ return this.proto.paginationCursor;
72
+ }
73
+ }
74
+ //# sourceMappingURL=rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../../src/lib/store/rpc.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@waku/core","version":"0.0.31-08fc2d1.0","description":"TypeScript implementation of the Waku v2 protocol","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./lib/message/version_0":{"types":"./dist/lib/message/version_0.d.ts","import":"./dist/lib/message/version_0.js"},"./lib/base_protocol":{"types":"./dist/lib/base_protocol.d.ts","import":"./dist/lib/base_protocol.js"}},"typesVersions":{"*":{"lib/*":["dist/lib/*"],"constants/*":["dist/constants/*"]}},"type":"module","homepage":"https://github.com/waku-org/js-waku/tree/master/packages/core#readme","repository":{"type":"git","url":"https://github.com/waku-org/js-waku.git"},"bugs":{"url":"https://github.com/waku-org/js-waku/issues"},"license":"MIT OR Apache-2.0","keywords":["waku","decentralised","communication","web3","ethereum","dapps"],"scripts":{"build":"run-s build:**","build:esm":"tsc","build:bundle":"rollup --config rollup.config.js","fix":"run-s fix:*","fix:lint":"eslint src *.js --fix","check":"run-s check:*","check:tsc":"tsc -p tsconfig.dev.json","check:lint":"eslint src *.js","check:spelling":"cspell \"{README.md,src/**/*.ts}\"","test":"NODE_ENV=test run-s test:*","test:node":"NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json mocha","test:browser":"NODE_ENV=test karma start karma.conf.cjs","watch:build":"tsc -p tsconfig.json -w","watch:test":"mocha --watch","prepublish":"npm run build","reset-hard":"git clean -dfx -e .idea && git reset --hard && npm i && npm run build"},"engines":{"node":">=18"},"dependencies":{"@libp2p/ping":"^1.0.12","@waku/enr":"0.0.25-08fc2d1.0","@waku/interfaces":"0.0.26-08fc2d1.0","@waku/proto":"0.0.8-08fc2d1.0","@waku/utils":"0.0.19-08fc2d1.0","debug":"^4.3.4","it-all":"^3.0.4","it-length-prefixed":"^9.0.4","it-pipe":"^3.0.1","p-event":"^6.0.1","uint8arraylist":"^2.4.3","uuid":"^9.0.0"},"devDependencies":{"@multiformats/multiaddr":"^12.0.0","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-json":"^6.0.0","@rollup/plugin-node-resolve":"^15.2.3","@types/chai":"^4.3.11","@types/debug":"^4.1.12","@types/mocha":"^10.0.6","@types/uuid":"^9.0.8","@waku/build-utils":"*","chai":"^4.3.10","cspell":"^8.6.1","fast-check":"^3.19.0","ignore-loader":"^0.1.2","isomorphic-fetch":"^3.0.0","mocha":"^10.3.0","npm-run-all":"^4.1.5","process":"^0.11.10","rollup":"^4.12.0"},"peerDependencies":{"@multiformats/multiaddr":"^12.0.0","libp2p":"^1.1.2","@waku/enr":"0.0.25-08fc2d1.0","@waku/interfaces":"0.0.26-08fc2d1.0","@waku/proto":"0.0.8-08fc2d1.0","@waku/utils":"0.0.19-08fc2d1.0"},"peerDependenciesMeta":{"@multiformats/multiaddr":{"optional":true},"@waku/interfaces":{"optional":true}},"files":["dist","bundle","src/**/*.ts","!**/*.spec.*","!**/*.json","CHANGELOG.md","LICENSE","README.md"]}
1
+ {"name":"@waku/core","version":"0.0.31-88a29c3.0","description":"TypeScript implementation of the Waku v2 protocol","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./lib/message/version_0":{"types":"./dist/lib/message/version_0.d.ts","import":"./dist/lib/message/version_0.js"},"./lib/base_protocol":{"types":"./dist/lib/base_protocol.d.ts","import":"./dist/lib/base_protocol.js"}},"typesVersions":{"*":{"lib/*":["dist/lib/*"],"constants/*":["dist/constants/*"]}},"type":"module","homepage":"https://github.com/waku-org/js-waku/tree/master/packages/core#readme","repository":{"type":"git","url":"https://github.com/waku-org/js-waku.git"},"bugs":{"url":"https://github.com/waku-org/js-waku/issues"},"license":"MIT OR Apache-2.0","keywords":["waku","decentralised","communication","web3","ethereum","dapps"],"scripts":{"build":"run-s build:**","build:esm":"tsc","build:bundle":"rollup --config rollup.config.js","fix":"run-s fix:*","fix:lint":"eslint src *.js --fix","check":"run-s check:*","check:tsc":"tsc -p tsconfig.dev.json","check:lint":"eslint src *.js","check:spelling":"cspell \"{README.md,src/**/*.ts}\"","test":"NODE_ENV=test run-s test:*","test:node":"NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json mocha","test:browser":"NODE_ENV=test karma start karma.conf.cjs","watch:build":"tsc -p tsconfig.json -w","watch:test":"mocha --watch","prepublish":"npm run build","reset-hard":"git clean -dfx -e .idea && git reset --hard && npm i && npm run build"},"engines":{"node":">=18"},"dependencies":{"@libp2p/ping":"^1.0.12","@waku/enr":"0.0.25-88a29c3.0","@waku/interfaces":"0.0.26-88a29c3.0","@waku/proto":"0.0.8-88a29c3.0","@waku/utils":"0.0.19-88a29c3.0","debug":"^4.3.4","it-all":"^3.0.4","it-length-prefixed":"^9.0.4","it-pipe":"^3.0.1","p-event":"^6.0.1","uint8arraylist":"^2.4.3","uuid":"^9.0.0"},"devDependencies":{"@multiformats/multiaddr":"^12.0.0","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-json":"^6.0.0","@rollup/plugin-node-resolve":"^15.2.3","@types/chai":"^4.3.11","@types/debug":"^4.1.12","@types/mocha":"^10.0.6","@types/uuid":"^9.0.8","@waku/build-utils":"*","chai":"^4.3.10","cspell":"^8.6.1","fast-check":"^3.19.0","ignore-loader":"^0.1.2","isomorphic-fetch":"^3.0.0","mocha":"^10.3.0","npm-run-all":"^4.1.5","process":"^0.11.10","rollup":"^4.12.0"},"peerDependencies":{"@multiformats/multiaddr":"^12.0.0","libp2p":"^1.1.2","@waku/enr":"0.0.25-88a29c3.0","@waku/interfaces":"0.0.26-88a29c3.0","@waku/proto":"0.0.8-88a29c3.0","@waku/utils":"0.0.19-88a29c3.0"},"peerDependenciesMeta":{"@multiformats/multiaddr":{"optional":true},"@waku/interfaces":{"optional":true}},"files":["dist","bundle","src/**/*.ts","!**/*.spec.*","!**/*.json","CHANGELOG.md","LICENSE","README.md"]}
package/src/index.ts CHANGED
@@ -15,12 +15,12 @@ export { LightPushCodec, LightPushCore } from "./lib/light_push/index.js";
15
15
  export * as waku_store from "./lib/store/index.js";
16
16
  export { StoreCore } from "./lib/store/index.js";
17
17
 
18
- export { PageDirection } from "./lib/store/index.js";
19
-
20
18
  export { waitForRemotePeer } from "./lib/wait_for_remote_peer.js";
21
19
 
22
20
  export { ConnectionManager } from "./lib/connection_manager.js";
23
21
 
22
+ export { getHealthManager } from "./lib/health_manager.js";
23
+
24
24
  export { KeepAliveManager } from "./lib/keep_alive_manager.js";
25
25
  export { StreamManager } from "./lib/stream_manager/index.js";
26
26
 
@@ -0,0 +1,90 @@
1
+ import {
2
+ HealthStatus,
3
+ type IHealthManager,
4
+ NodeHealth,
5
+ type ProtocolHealth,
6
+ Protocols
7
+ } from "@waku/interfaces";
8
+
9
+ class HealthManager implements IHealthManager {
10
+ public static instance: HealthManager;
11
+ private readonly health: NodeHealth;
12
+
13
+ private constructor() {
14
+ this.health = {
15
+ overallStatus: HealthStatus.Unhealthy,
16
+ protocolStatuses: new Map()
17
+ };
18
+ }
19
+
20
+ public static getInstance(): HealthManager {
21
+ if (!HealthManager.instance) {
22
+ HealthManager.instance = new HealthManager();
23
+ }
24
+ return HealthManager.instance;
25
+ }
26
+
27
+ public getHealthStatus(): HealthStatus {
28
+ return this.health.overallStatus;
29
+ }
30
+
31
+ public getProtocolStatus(protocol: Protocols): ProtocolHealth | undefined {
32
+ return this.health.protocolStatuses.get(protocol);
33
+ }
34
+
35
+ public updateProtocolHealth(
36
+ multicodec: string,
37
+ connectedPeers: number
38
+ ): void {
39
+ const protocol = this.getNameFromMulticodec(multicodec);
40
+
41
+ let status: HealthStatus = HealthStatus.Unhealthy;
42
+ if (connectedPeers == 1) {
43
+ status = HealthStatus.MinimallyHealthy;
44
+ } else if (connectedPeers >= 2) {
45
+ status = HealthStatus.SufficientlyHealthy;
46
+ }
47
+
48
+ this.health.protocolStatuses.set(protocol, {
49
+ name: protocol,
50
+ status: status,
51
+ lastUpdate: new Date()
52
+ });
53
+
54
+ this.updateOverallHealth();
55
+ }
56
+
57
+ private getNameFromMulticodec(multicodec: string): Protocols {
58
+ let name: Protocols;
59
+ if (multicodec.includes("filter")) {
60
+ name = Protocols.Filter;
61
+ } else if (multicodec.includes("lightpush")) {
62
+ name = Protocols.LightPush;
63
+ } else if (multicodec.includes("store")) {
64
+ name = Protocols.Store;
65
+ } else {
66
+ throw new Error(`Unknown protocol: ${multicodec}`);
67
+ }
68
+ return name;
69
+ }
70
+
71
+ private updateOverallHealth(): void {
72
+ const relevantProtocols = [Protocols.LightPush, Protocols.Filter];
73
+ const statuses = relevantProtocols.map(
74
+ (p) => this.getProtocolStatus(p)?.status
75
+ );
76
+
77
+ if (statuses.some((status) => status === HealthStatus.Unhealthy)) {
78
+ this.health.overallStatus = HealthStatus.Unhealthy;
79
+ } else if (
80
+ statuses.some((status) => status === HealthStatus.MinimallyHealthy)
81
+ ) {
82
+ this.health.overallStatus = HealthStatus.MinimallyHealthy;
83
+ } else {
84
+ this.health.overallStatus = HealthStatus.SufficientlyHealthy;
85
+ }
86
+ }
87
+ }
88
+
89
+ export const getHealthManager = (): HealthManager =>
90
+ HealthManager.getInstance();
@@ -1,13 +1,12 @@
1
1
  import type { Peer } from "@libp2p/interface";
2
2
  import {
3
- Cursor,
4
3
  IDecodedMessage,
5
4
  IDecoder,
6
5
  IStoreCore,
7
6
  Libp2p,
8
- ProtocolCreateOptions
7
+ ProtocolCreateOptions,
8
+ QueryRequestParams
9
9
  } from "@waku/interfaces";
10
- import { proto_store as proto } from "@waku/proto";
11
10
  import { Logger } from "@waku/utils";
12
11
  import all from "it-all";
13
12
  import * as lp from "it-length-prefixed";
@@ -17,63 +16,30 @@ import { Uint8ArrayList } from "uint8arraylist";
17
16
  import { BaseProtocol } from "../base_protocol.js";
18
17
  import { toProtoMessage } from "../to_proto_message.js";
19
18
 
20
- import { HistoryRpc, PageDirection, Params } from "./history_rpc.js";
21
-
22
- import HistoryError = proto.HistoryResponse.HistoryError;
19
+ import {
20
+ DEFAULT_PAGE_SIZE,
21
+ MAX_PAGE_SIZE,
22
+ StoreQueryRequest,
23
+ StoreQueryResponse
24
+ } from "./rpc.js";
23
25
 
24
26
  const log = new Logger("store");
25
27
 
26
- export const StoreCodec = "/vac/waku/store/2.0.0-beta4";
27
-
28
- export { PageDirection, Params };
29
-
30
- export interface TimeFilter {
31
- startTime: Date;
32
- endTime: Date;
33
- }
34
-
35
- export interface QueryOptions {
36
- /**
37
- * The direction in which pages are retrieved:
38
- * - { @link PageDirection.BACKWARD }: Most recent page first.
39
- * - { @link PageDirection.FORWARD }: Oldest page first.
40
- *
41
- * Note: This does not affect the ordering of messages with the page
42
- * (the oldest message is always first).
43
- *
44
- * @default { @link PageDirection.BACKWARD }
45
- */
46
- pageDirection?: PageDirection;
47
- /**
48
- * The number of message per page.
49
- *
50
- * @default { @link DefaultPageSize }
51
- */
52
- pageSize?: number;
53
- /**
54
- * Retrieve messages with a timestamp within the provided values.
55
- */
56
- timeFilter?: TimeFilter;
57
- /**
58
- * Cursor as an index to start a query from.
59
- * The cursor index will be exclusive (i.e. the message at the cursor index will not be included in the result).
60
- * If undefined, the query will start from the beginning or end of the history, depending on the page direction.
61
- */
62
- cursor?: Cursor;
63
- }
28
+ export const StoreCodec = "/vac/waku/store-query/3.0.0";
64
29
 
65
- /**
66
- * Implements the [Waku v2 Store protocol](https://rfc.vac.dev/spec/13/).
67
- *
68
- * The Waku Store protocol can be used to retrieved historical messages.
69
- */
70
30
  export class StoreCore extends BaseProtocol implements IStoreCore {
71
31
  public constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
72
- super(StoreCodec, libp2p.components, log, options!.pubsubTopics!, options);
32
+ super(
33
+ StoreCodec,
34
+ libp2p.components,
35
+ log,
36
+ options?.pubsubTopics || [],
37
+ options
38
+ );
73
39
  }
74
40
 
75
41
  public async *queryPerPage<T extends IDecodedMessage>(
76
- queryOpts: Params,
42
+ queryOpts: QueryRequestParams,
77
43
  decoders: Map<string, IDecoder<T>>,
78
44
  peer: Peer
79
45
  ): AsyncGenerator<Promise<T | undefined>[]> {
@@ -86,11 +52,12 @@ export class StoreCore extends BaseProtocol implements IStoreCore {
86
52
  );
87
53
  }
88
54
 
89
- let currentCursor = queryOpts.cursor;
55
+ let currentCursor = queryOpts.paginationCursor;
90
56
  while (true) {
91
- queryOpts.cursor = currentCursor;
92
-
93
- const historyRpcQuery = HistoryRpc.createQuery(queryOpts);
57
+ const storeQueryRequest = StoreQueryRequest.create({
58
+ ...queryOpts,
59
+ paginationCursor: currentCursor
60
+ });
94
61
 
95
62
  let stream;
96
63
  try {
@@ -101,7 +68,7 @@ export class StoreCore extends BaseProtocol implements IStoreCore {
101
68
  }
102
69
 
103
70
  const res = await pipe(
104
- [historyRpcQuery.encode()],
71
+ [storeQueryRequest.encode()],
105
72
  lp.encode,
106
73
  stream,
107
74
  lp.decode,
@@ -113,61 +80,57 @@ export class StoreCore extends BaseProtocol implements IStoreCore {
113
80
  bytes.append(chunk);
114
81
  });
115
82
 
116
- const reply = historyRpcQuery.decode(bytes);
117
-
118
- if (!reply.response) {
119
- log.warn("Stopping pagination due to store `response` field missing");
120
- break;
121
- }
122
-
123
- const response = reply.response as proto.HistoryResponse;
83
+ const storeQueryResponse = StoreQueryResponse.decode(bytes);
124
84
 
125
- if (response.error && response.error !== HistoryError.NONE) {
126
- throw "History response contains an Error: " + response.error;
85
+ if (
86
+ !storeQueryResponse.statusCode ||
87
+ storeQueryResponse.statusCode >= 300
88
+ ) {
89
+ const errorMessage = `Store query failed with status code: ${storeQueryResponse.statusCode}, description: ${storeQueryResponse.statusDesc}`;
90
+ log.error(errorMessage);
91
+ throw new Error(errorMessage);
127
92
  }
128
93
 
129
- if (!response.messages || !response.messages.length) {
130
- log.warn(
131
- "Stopping pagination due to store `response.messages` field missing or empty"
132
- );
94
+ if (!storeQueryResponse.messages || !storeQueryResponse.messages.length) {
95
+ log.warn("Stopping pagination due to empty messages in response");
133
96
  break;
134
97
  }
135
98
 
136
- log.error(`${response.messages.length} messages retrieved from store`);
99
+ log.info(
100
+ `${storeQueryResponse.messages.length} messages retrieved from store`
101
+ );
137
102
 
138
- yield response.messages.map((protoMsg) => {
139
- const contentTopic = protoMsg.contentTopic;
140
- if (typeof contentTopic !== "undefined") {
103
+ const decodedMessages = storeQueryResponse.messages.map((protoMsg) => {
104
+ if (!protoMsg.message) {
105
+ return Promise.resolve(undefined);
106
+ }
107
+ const contentTopic = protoMsg.message.contentTopic;
108
+ if (contentTopic) {
141
109
  const decoder = decoders.get(contentTopic);
142
110
  if (decoder) {
143
111
  return decoder.fromProtoObj(
144
- queryOpts.pubsubTopic,
145
- toProtoMessage(protoMsg)
112
+ protoMsg.pubsubTopic || "",
113
+ toProtoMessage(protoMsg.message)
146
114
  );
147
115
  }
148
116
  }
149
117
  return Promise.resolve(undefined);
150
118
  });
151
119
 
152
- const nextCursor = response.pagingInfo?.cursor;
153
- if (typeof nextCursor === "undefined") {
154
- // If the server does not return cursor then there is an issue,
155
- // Need to abort, or we end up in an infinite loop
156
- log.warn(
157
- "Stopping pagination due to `response.pagingInfo.cursor` missing from store response"
158
- );
159
- break;
160
- }
120
+ yield decodedMessages;
161
121
 
162
- currentCursor = nextCursor;
122
+ if (queryOpts.paginationForward) {
123
+ currentCursor =
124
+ storeQueryResponse.messages[storeQueryResponse.messages.length - 1]
125
+ .messageHash;
126
+ } else {
127
+ currentCursor = storeQueryResponse.messages[0].messageHash;
128
+ }
163
129
 
164
- const responsePageSize = response.pagingInfo?.pageSize;
165
- const queryPageSize = historyRpcQuery.query?.pagingInfo?.pageSize;
166
130
  if (
167
- // Response page size smaller than query, meaning this is the last page
168
- responsePageSize &&
169
- queryPageSize &&
170
- responsePageSize < queryPageSize
131
+ storeQueryResponse.messages.length > MAX_PAGE_SIZE &&
132
+ storeQueryResponse.messages.length <
133
+ (queryOpts.paginationLimit || DEFAULT_PAGE_SIZE)
171
134
  ) {
172
135
  break;
173
136
  }