@subsquid/portal-client 0.3.2 → 0.5.0-portal-api.f9b61c

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.
Files changed (131) hide show
  1. package/lib/client.d.ts +40 -18
  2. package/lib/client.d.ts.map +1 -1
  3. package/lib/client.js +170 -188
  4. package/lib/client.js.map +1 -1
  5. package/lib/query/common/data.d.ts +21 -0
  6. package/lib/query/common/data.d.ts.map +1 -0
  7. package/lib/query/common/data.js +3 -0
  8. package/lib/query/common/data.js.map +1 -0
  9. package/lib/query/common/query.d.ts +7 -0
  10. package/lib/query/common/query.d.ts.map +1 -0
  11. package/lib/query/common/query.js +3 -0
  12. package/lib/query/common/query.js.map +1 -0
  13. package/lib/query/evm/data.d.ts +159 -0
  14. package/lib/query/evm/data.d.ts.map +1 -0
  15. package/lib/query/evm/data.js +3 -0
  16. package/lib/query/evm/data.js.map +1 -0
  17. package/lib/query/evm/fields.d.ts +50 -0
  18. package/lib/query/evm/fields.d.ts.map +1 -0
  19. package/lib/query/evm/fields.js +3 -0
  20. package/lib/query/evm/fields.js.map +1 -0
  21. package/lib/query/evm/index.d.ts +4 -0
  22. package/lib/query/evm/index.d.ts.map +1 -0
  23. package/lib/query/evm/index.js +7 -0
  24. package/lib/query/evm/index.js.map +1 -0
  25. package/lib/query/evm/query.d.ts +54 -0
  26. package/lib/query/evm/query.d.ts.map +1 -0
  27. package/lib/query/evm/query.js +3 -0
  28. package/lib/query/evm/query.js.map +1 -0
  29. package/lib/query/evm/schema.d.ts +322 -0
  30. package/lib/query/evm/schema.d.ts.map +1 -0
  31. package/lib/query/evm/schema.js +224 -0
  32. package/lib/query/evm/schema.js.map +1 -0
  33. package/lib/query/index.d.ts +576 -8
  34. package/lib/query/index.d.ts.map +1 -1
  35. package/lib/query/index.js +15 -24
  36. package/lib/query/index.js.map +1 -1
  37. package/lib/query/solana/data.d.ts +115 -0
  38. package/lib/query/solana/data.d.ts.map +1 -0
  39. package/lib/query/solana/data.js +3 -0
  40. package/lib/query/solana/data.js.map +1 -0
  41. package/lib/query/solana/fields.d.ts +31 -0
  42. package/lib/query/solana/fields.d.ts.map +1 -0
  43. package/lib/query/solana/fields.js +3 -0
  44. package/lib/query/solana/fields.js.map +1 -0
  45. package/lib/query/solana/index.d.ts +4 -0
  46. package/lib/query/solana/index.d.ts.map +1 -0
  47. package/lib/query/solana/index.js +7 -0
  48. package/lib/query/solana/index.js.map +1 -0
  49. package/lib/query/solana/query.d.ts +74 -0
  50. package/lib/query/solana/query.d.ts.map +1 -0
  51. package/lib/query/solana/query.js +3 -0
  52. package/lib/query/solana/query.js.map +1 -0
  53. package/lib/query/solana/schema.d.ts +160 -0
  54. package/lib/query/solana/schema.d.ts.map +1 -0
  55. package/lib/query/solana/schema.js +130 -0
  56. package/lib/query/solana/schema.js.map +1 -0
  57. package/lib/query/substrate/data.d.ts +98 -0
  58. package/lib/query/substrate/data.d.ts.map +1 -0
  59. package/lib/query/substrate/data.js +3 -0
  60. package/lib/query/substrate/data.js.map +1 -0
  61. package/lib/query/substrate/fields.d.ts +22 -0
  62. package/lib/query/substrate/fields.d.ts.map +1 -0
  63. package/lib/query/substrate/fields.js +3 -0
  64. package/lib/query/substrate/fields.js.map +1 -0
  65. package/lib/query/substrate/index.d.ts +4 -0
  66. package/lib/query/substrate/index.d.ts.map +1 -0
  67. package/lib/query/substrate/index.js +7 -0
  68. package/lib/query/substrate/index.js.map +1 -0
  69. package/lib/query/substrate/query.d.ts +50 -0
  70. package/lib/query/substrate/query.d.ts.map +1 -0
  71. package/lib/query/substrate/query.js +3 -0
  72. package/lib/query/substrate/query.js.map +1 -0
  73. package/lib/query/substrate/schema.d.ts +102 -0
  74. package/lib/query/substrate/schema.d.ts.map +1 -0
  75. package/lib/query/substrate/schema.js +88 -0
  76. package/lib/query/substrate/schema.js.map +1 -0
  77. package/lib/query/type-util.d.ts +13 -0
  78. package/lib/query/type-util.d.ts.map +1 -0
  79. package/lib/query/type-util.js +3 -0
  80. package/lib/query/type-util.js.map +1 -0
  81. package/lib/query/util.d.ts +5 -0
  82. package/lib/query/util.d.ts.map +1 -0
  83. package/lib/query/util.js +23 -0
  84. package/lib/query/util.js.map +1 -0
  85. package/lib/util.d.ts +19 -0
  86. package/lib/util.d.ts.map +1 -0
  87. package/lib/util.js +57 -0
  88. package/lib/util.js.map +1 -0
  89. package/package.json +5 -5
  90. package/src/client.ts +234 -245
  91. package/src/query/common/data.ts +24 -0
  92. package/src/query/common/query.ts +6 -0
  93. package/src/query/evm/data.ts +182 -0
  94. package/src/query/evm/fields.ts +105 -0
  95. package/src/query/evm/index.ts +3 -0
  96. package/src/query/evm/query.ts +59 -0
  97. package/src/query/evm/schema.ts +277 -0
  98. package/src/query/index.ts +19 -36
  99. package/src/query/solana/data.ts +132 -0
  100. package/src/query/solana/fields.ts +42 -0
  101. package/src/query/solana/index.ts +3 -0
  102. package/src/query/solana/query.ts +89 -0
  103. package/src/query/solana/schema.ts +164 -0
  104. package/src/query/substrate/data.ts +101 -0
  105. package/src/query/substrate/fields.ts +30 -0
  106. package/src/query/substrate/index.ts +3 -0
  107. package/src/query/substrate/query.ts +60 -0
  108. package/src/query/substrate/schema.ts +114 -0
  109. package/src/query/type-util.ts +25 -0
  110. package/src/query/util.ts +23 -0
  111. package/src/util.ts +56 -0
  112. package/lib/query/common.d.ts +0 -56
  113. package/lib/query/common.d.ts.map +0 -1
  114. package/lib/query/common.js +0 -16
  115. package/lib/query/common.js.map +0 -1
  116. package/lib/query/evm.d.ts +0 -267
  117. package/lib/query/evm.d.ts.map +0 -1
  118. package/lib/query/evm.js +0 -245
  119. package/lib/query/evm.js.map +0 -1
  120. package/lib/query/solana.d.ts +0 -224
  121. package/lib/query/solana.d.ts.map +0 -1
  122. package/lib/query/solana.js +0 -121
  123. package/lib/query/solana.js.map +0 -1
  124. package/lib/query/substrate.d.ts +0 -173
  125. package/lib/query/substrate.d.ts.map +0 -1
  126. package/lib/query/substrate.js +0 -71
  127. package/lib/query/substrate.js.map +0 -1
  128. package/src/query/common.ts +0 -83
  129. package/src/query/evm.ts +0 -677
  130. package/src/query/solana.ts +0 -438
  131. package/src/query/substrate.ts +0 -288
package/lib/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { HttpClient, HttpClientOptions } from '@subsquid/http-client';
2
- import { GetBlock, evm, PortalBlock, PortalQuery, Query, solana, substrate } from './query';
2
+ import { type AnyQuery, type GetQueryBlock } from './query';
3
3
  export * from './query';
4
4
  export interface PortalClientOptions {
5
5
  /**
@@ -12,17 +12,17 @@ export interface PortalClientOptions {
12
12
  http?: HttpClient | HttpClientOptions;
13
13
  /**
14
14
  * Minimum number of bytes to return.
15
- * @default 10_485_760 (10MB)
15
+ * @deprecated not used
16
16
  */
17
17
  minBytes?: number;
18
18
  /**
19
19
  * Maximum number of bytes to return.
20
- * @default minBytes
20
+ * @default 52_428_800 (50MB)
21
21
  */
22
22
  maxBytes?: number;
23
23
  /**
24
24
  * Maximum time between stream data in milliseconds for return.
25
- * @default 300
25
+ * @default 500
26
26
  */
27
27
  maxIdleTime?: number;
28
28
  /**
@@ -46,16 +46,34 @@ export interface PortalRequestOptions {
46
46
  }
47
47
  export interface PortalStreamOptions {
48
48
  request?: Omit<PortalRequestOptions, 'abort'>;
49
- minBytes?: number;
50
49
  maxBytes?: number;
51
50
  maxIdleTime?: number;
52
51
  maxWaitTime?: number;
53
52
  headPollInterval?: number;
54
53
  }
54
+ export interface PortalStreamBaseResponse {
55
+ headNumber?: number;
56
+ finalizedHeadNumber?: number;
57
+ finalizedHeadHash?: string;
58
+ }
59
+ export interface PortalStreamDataResponse extends PortalStreamBaseResponse {
60
+ type: 'data';
61
+ data: AsyncIterable<Uint8Array> | null;
62
+ }
63
+ export interface PortalStreamNoDataResponse extends PortalStreamBaseResponse {
64
+ type: 'no-data';
65
+ }
66
+ export interface PortalStreamForkResponse extends PortalStreamBaseResponse {
67
+ type: 'fork';
68
+ previousBlocks: BlockRef[];
69
+ }
70
+ export type PortalStreamResponse = PortalStreamDataResponse | PortalStreamNoDataResponse | PortalStreamForkResponse;
55
71
  export type PortalStreamData<B> = {
56
72
  blocks: B[];
57
- finalizedHead?: BlockRef;
58
73
  meta: {
74
+ finalizedHeadNumber?: number;
75
+ finalizedHeadHash?: string;
76
+ headNumber?: number;
59
77
  bytes: number;
60
78
  };
61
79
  };
@@ -69,31 +87,35 @@ export declare class PortalClient {
69
87
  private url;
70
88
  private client;
71
89
  private headPollInterval;
72
- private minBytes;
73
90
  private maxBytes;
74
91
  private maxIdleTime;
75
92
  private maxWaitTime;
76
93
  constructor(options: PortalClientOptions);
77
94
  private getDatasetUrl;
78
- getHead(options?: PortalRequestOptions): Promise<BlockRef | undefined>;
95
+ getHead(options?: PortalRequestOptions, finalized?: boolean): Promise<BlockRef | undefined>;
79
96
  getFinalizedHead(options?: PortalRequestOptions): Promise<BlockRef | undefined>;
80
97
  /**
81
- * @deprecated
98
+ * Waits until the finalized head reaches or exceeds the specified block number.
99
+ * @param blockNumber - The block number to wait for finalization
100
+ * @param options - Request options including abort signal and poll interval
101
+ * @returns The finalized head once it reaches the target block number
82
102
  */
83
- getFinalizedHeight(options?: PortalRequestOptions): Promise<number>;
84
- getFinalizedQuery<Q extends Query>(query: Q, options?: PortalRequestOptions): Promise<GetBlock<Q>[]>;
85
- getQuery<Q extends PortalQuery = PortalQuery, R extends PortalBlock = PortalBlock>(query: Q, options?: PortalRequestOptions): Promise<R[]>;
86
- getFinalizedStream<Q extends evm.Query | solana.Query | substrate.Query>(query: Q, options?: PortalStreamOptions): PortalStream<GetBlock<Q>>;
87
- getStream<Q extends evm.Query | solana.Query | substrate.Query>(query: Q, options?: PortalStreamOptions): PortalStream<GetBlock<Q>>;
103
+ waitForFinalization(blockNumber: number, options?: PortalRequestOptions & {
104
+ pollInterval?: number;
105
+ }): Promise<BlockRef>;
106
+ getStream<Q extends AnyQuery>(query: Q, options?: PortalStreamOptions, finalized?: boolean): PortalStream<GetQueryBlock<Q>>;
107
+ getFinalizedStream<Q extends AnyQuery>(query: Q, options?: PortalStreamOptions): PortalStream<GetQueryBlock<Q>>;
88
108
  private getStreamOptions;
89
109
  private getStreamRequest;
90
110
  private request;
91
111
  }
92
112
  export declare class ForkException extends Error {
93
- readonly previousBlocks: BlockRef[];
94
- readonly head: BlockRef;
95
- readonly name = "ForkError";
96
- constructor(previousBlocks: BlockRef[], head: BlockRef);
113
+ blockNumber: number;
114
+ parentBlockHash: string;
115
+ previousBlocks: BlockRef[];
116
+ constructor(blockNumber: number, parentBlockHash: string, previousBlocks: BlockRef[]);
117
+ get name(): string;
118
+ get isSubsquidForkException(): true;
97
119
  }
98
120
  export declare function isForkException(err: unknown): err is ForkException;
99
121
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,UAAU,EAAE,iBAAiB,EAA0C,MAAM,uBAAuB,CAAA;AAWtH,OAAO,EAAC,QAAQ,EAAE,GAAG,EAAkB,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAC,MAAM,SAAS,CAAA;AAGzG,cAAc,SAAS,CAAA;AAIvB,MAAM,WAAW,mBAAmB;IAChC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IAEX;;OAEG;IACH,IAAI,CAAC,EAAE,UAAU,GAAG,iBAAiB,CAAA;IAErC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACjC,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,WAAW,CAAA;CACtB;AAED,MAAM,WAAW,mBAAmB;IAChC,OAAO,CAAC,EAAE,IAAI,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAA;IAE7C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IAC9B,MAAM,EAAE,CAAC,EAAE,CAAA;IACX,aAAa,CAAC,EAAE,QAAQ,CAAA;IACxB,IAAI,EAAE;QACF,KAAK,EAAE,MAAM,CAAA;KAChB,CAAA;CACJ,CAAA;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,CAAE,SAAQ,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;CAAG;AAE9E,MAAM,MAAM,QAAQ,GAAG;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,qBAAa,YAAY;IACrB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,gBAAgB,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,WAAW,CAAQ;gBAEf,OAAO,EAAE,mBAAmB;IAUxC,OAAO,CAAC,aAAa;IAUf,OAAO,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAKtE,gBAAgB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAKrF;;OAEG;IACG,kBAAkB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;IAMzE,iBAAiB,CAAC,CAAC,SAAS,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAqBpG,QAAQ,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,CAAC,SAAS,WAAW,GAAG,WAAW,EAC7E,KAAK,EAAE,CAAC,EACR,OAAO,CAAC,EAAE,oBAAoB,GAC/B,OAAO,CAAC,CAAC,EAAE,CAAC;IAqBf,kBAAkB,CAAC,CAAC,SAAS,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,EACnE,KAAK,EAAE,CAAC,EACR,OAAO,CAAC,EAAE,mBAAmB,GAC9B,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAM5B,SAAS,CAAC,CAAC,SAAS,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,EAC1D,KAAK,EAAE,CAAC,EACR,OAAO,CAAC,EAAE,mBAAmB,GAC9B,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAM5B,OAAO,CAAC,gBAAgB;YAoBV,gBAAgB;IA0C9B,OAAO,CAAC,OAAO;CASlB;AAySD,qBAAa,aAAc,SAAQ,KAAK;IAGxB,QAAQ,CAAC,cAAc,EAAE,QAAQ,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ;IAFxE,QAAQ,CAAC,IAAI,eAAc;gBAEN,cAAc,EAAE,QAAQ,EAAE,EAAW,IAAI,EAAE,QAAQ;CAQ3E;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,aAAa,CAIlE"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/lib/client.js CHANGED
@@ -18,8 +18,9 @@ exports.ForkException = exports.PortalClient = void 0;
18
18
  exports.isForkException = isForkException;
19
19
  const http_client_1 = require("@subsquid/http-client");
20
20
  const util_internal_1 = require("@subsquid/util-internal");
21
- const query_1 = require("./query");
22
21
  const util_internal_validation_1 = require("@subsquid/util-internal-validation");
22
+ const util_1 = require("./util");
23
+ const query_1 = require("./query");
23
24
  __exportStar(require("./query"), exports);
24
25
  const USER_AGENT = `@subsquid/portal-client (https://sqd.ai)`;
25
26
  class PortalClient {
@@ -27,9 +28,8 @@ class PortalClient {
27
28
  this.url = new URL(options.url);
28
29
  this.client = options.http instanceof http_client_1.HttpClient ? options.http : new http_client_1.HttpClient(options.http);
29
30
  this.headPollInterval = options.headPollInterval ?? 0;
30
- this.minBytes = options.minBytes ?? 10 * 1024 * 1024;
31
- this.maxBytes = options.maxBytes ?? this.minBytes;
32
- this.maxIdleTime = options.maxIdleTime ?? 300;
31
+ this.maxBytes = options.maxBytes ?? 50 * 1024 * 1024;
32
+ this.maxIdleTime = options.maxIdleTime ?? 500;
33
33
  this.maxWaitTime = options.maxWaitTime ?? 5000;
34
34
  }
35
35
  getDatasetUrl(path) {
@@ -42,69 +42,40 @@ class PortalClient {
42
42
  }
43
43
  return u.toString();
44
44
  }
45
- async getHead(options) {
46
- const res = await this.request('GET', this.getDatasetUrl('head'), options);
45
+ async getHead(options, finalized) {
46
+ const res = await this.request('GET', this.getDatasetUrl(!finalized ? 'head' : 'finalized-head'), options);
47
47
  return res.body ?? undefined;
48
48
  }
49
- async getFinalizedHead(options) {
50
- const res = await this.request('GET', this.getDatasetUrl('finalized-head'), options);
51
- return res.body ?? undefined;
49
+ getFinalizedHead(options) {
50
+ return this.getHead(options, true);
52
51
  }
53
52
  /**
54
- * @deprecated
53
+ * Waits until the finalized head reaches or exceeds the specified block number.
54
+ * @param blockNumber - The block number to wait for finalization
55
+ * @param options - Request options including abort signal and poll interval
56
+ * @returns The finalized head once it reaches the target block number
55
57
  */
56
- async getFinalizedHeight(options) {
57
- let { body } = await this.request('GET', this.getDatasetUrl('finalized-stream/height'), options);
58
- let height = parseInt(body);
59
- return height;
60
- }
61
- getFinalizedQuery(query, options) {
62
- // FIXME: is it needed or it is better to always use stream?
63
- return this.request('POST', this.getDatasetUrl(`finalized-stream`), {
64
- ...options,
65
- json: query,
66
- })
67
- .catch((0, util_internal_1.withErrorContext)({
68
- archiveQuery: query,
69
- }))
70
- .then((res) => {
71
- let blocks = res.body
72
- .toString('utf8')
73
- .trimEnd()
74
- .split('\n')
75
- .map((line) => JSON.parse(line));
76
- return blocks;
77
- });
58
+ async waitForFinalization(blockNumber, options) {
59
+ let { pollInterval = this.headPollInterval || 1000, ...requestOptions } = options ?? {};
60
+ while (true) {
61
+ options?.abort?.throwIfAborted();
62
+ let head = await this.getFinalizedHead(requestOptions);
63
+ if (head && head.number >= blockNumber) {
64
+ return head;
65
+ }
66
+ await (0, util_internal_1.wait)(pollInterval, options?.abort);
67
+ }
78
68
  }
79
- getQuery(query, options) {
80
- // FIXME: is it needed or it is better to always use stream?
81
- return this.request('POST', this.getDatasetUrl(`stream`), {
82
- ...options,
83
- json: query,
84
- })
85
- .catch((0, util_internal_1.withErrorContext)({
86
- archiveQuery: query,
87
- }))
88
- .then((res) => {
89
- let blocks = res.body
90
- .toString('utf8')
91
- .trimEnd()
92
- .split('\n')
93
- .map((line) => JSON.parse(line));
94
- return blocks;
95
- });
69
+ getStream(query, options, finalized) {
70
+ return createPortalStream(query, this.getStreamOptions(options), async (q, o) => this.getStreamRequest(!finalized ? 'stream' : 'finalized-stream', q, o));
96
71
  }
97
72
  getFinalizedStream(query, options) {
98
- return createPortalStream(query, this.getStreamOptions(options), async (q, o) => this.getStreamRequest('finalized-stream', q, o));
99
- }
100
- getStream(query, options) {
101
- return createPortalStream(query, this.getStreamOptions(options), async (q, o) => this.getStreamRequest('stream', q, o));
73
+ return this.getStream(query, options, true);
102
74
  }
103
75
  getStreamOptions(options) {
104
- let { headPollInterval = this.headPollInterval, minBytes = this.minBytes, maxBytes = this.maxBytes, maxIdleTime = this.maxIdleTime, maxWaitTime = this.maxWaitTime, request = {}, } = options ?? {};
76
+ let { headPollInterval = this.headPollInterval, maxBytes = this.maxBytes, maxIdleTime = this.maxIdleTime, maxWaitTime = this.maxWaitTime, request = {}, } = options ?? {};
105
77
  return {
106
78
  headPollInterval,
107
- minBytes,
108
79
  maxBytes,
109
80
  maxIdleTime,
110
81
  maxWaitTime,
@@ -120,28 +91,29 @@ class PortalClient {
120
91
  }).catch((0, util_internal_1.withErrorContext)({
121
92
  query: query,
122
93
  }));
94
+ let headers = getPortalStreamHeaders(res.headers);
123
95
  switch (res.status) {
124
96
  case 200:
125
- let finalizedHead = getFinalizedHeadHeader(res.headers);
126
- let stream = res.body ? splitLines(res.body) : undefined;
127
97
  return {
128
- finalizedHead,
129
- stream,
98
+ ...headers,
99
+ type: 'data',
100
+ data: res.body ?? null,
130
101
  };
131
102
  case 204:
132
103
  return {
133
- finalizedHead: getFinalizedHeadHeader(res.headers),
104
+ ...headers,
105
+ type: 'no-data',
134
106
  };
135
107
  default:
136
108
  throw (0, util_internal_1.unexpectedCase)(res.status);
137
109
  }
138
110
  }
139
111
  catch (e) {
140
- if (isForkHttpError(e) && query.fromBlock != null && query.parentBlockHash != null) {
141
- e = new ForkException(e.response.body.previousBlocks, {
142
- number: query.fromBlock - 1,
143
- hash: query.parentBlockHash,
144
- });
112
+ if (isForkHttpError(e)) {
113
+ return {
114
+ type: 'fork',
115
+ previousBlocks: e.response.body.previousBlocks,
116
+ };
145
117
  }
146
118
  throw (0, util_internal_1.addErrorContext)(e, {
147
119
  query,
@@ -171,35 +143,35 @@ function isForkHttpError(err) {
171
143
  function createPortalStream(query, options, requestStream) {
172
144
  let { headPollInterval, request, ...bufferOptions } = options;
173
145
  let buffer = new PortalStreamBuffer(bufferOptions);
174
- let schema = (0, query_1.getBlockSchema)(query);
175
- let { fromBlock = 0, toBlock, parentBlockHash } = query;
146
+ let [normalizedQuery, schema] = (0, query_1.getQuery)(query);
147
+ let { fromBlock = 0, toBlock, parentBlockHash } = normalizedQuery;
176
148
  const ingest = async () => {
177
149
  while (!buffer.signal.aborted) {
178
150
  if (toBlock != null && fromBlock > toBlock)
179
151
  break;
180
152
  let res = await requestStream({
181
- ...query,
153
+ ...normalizedQuery,
182
154
  fromBlock,
183
155
  parentBlockHash,
184
156
  }, {
185
157
  ...request,
186
158
  abort: buffer.signal,
187
159
  });
188
- const finalizedHead = res.finalizedHead;
189
- // we are on head
190
- if (!('stream' in res)) {
191
- await buffer.put({ blocks: [], meta: { bytes: 0 }, finalizedHead });
160
+ if (res.type === 'fork') {
161
+ throw new ForkException(fromBlock, parentBlockHash, res.previousBlocks);
162
+ }
163
+ buffer.updateHead(res);
164
+ if (res.type === 'no-data') {
192
165
  buffer.flush();
193
166
  if (headPollInterval > 0) {
194
167
  await (0, util_internal_1.wait)(headPollInterval, buffer.signal);
195
168
  }
196
169
  continue;
197
170
  }
198
- // no data left on this range
199
- if (res.stream == null)
171
+ if (!res.data)
200
172
  break;
201
173
  try {
202
- for await (let data of res.stream) {
174
+ for await (let data of splitLines(res.data)) {
203
175
  buffer.signal.throwIfAborted();
204
176
  let blocks = [];
205
177
  let bytes = 0;
@@ -210,8 +182,9 @@ function createPortalStream(query, options, requestStream) {
210
182
  fromBlock = block.header.number + 1;
211
183
  parentBlockHash = block.header.hash;
212
184
  }
213
- await buffer.put({ blocks, finalizedHead, meta: { bytes } });
185
+ await buffer.put(blocks, bytes);
214
186
  }
187
+ buffer.flush();
215
188
  }
216
189
  catch (err) {
217
190
  if (buffer.signal.aborted)
@@ -221,141 +194,143 @@ function createPortalStream(query, options, requestStream) {
221
194
  }
222
195
  }
223
196
  }
197
+ buffer.flush();
224
198
  };
225
199
  ingest().then(() => buffer.close(), (err) => buffer.fail(err));
226
- return buffer.iterate();
200
+ return buffer;
227
201
  }
228
202
  class PortalStreamBuffer {
229
203
  get signal() {
230
204
  return this.abortController.signal;
231
205
  }
232
206
  constructor(options) {
233
- this.state = 'pending';
234
- this.readyFuture = (0, util_internal_1.createFuture)();
235
- this.takeFuture = (0, util_internal_1.createFuture)();
236
- this.putFuture = (0, util_internal_1.createFuture)();
207
+ this.blocks = [];
208
+ this.bytes = 0;
209
+ this.headUpdated = false;
210
+ this.state = 'open';
211
+ this.waitTimeouted = false;
212
+ this.putMutex = new util_1.Semaphore(false);
213
+ this.takeMutex = new util_1.Semaphore(true);
237
214
  this.abortController = new AbortController();
238
- this.maxWaitTime = options.maxWaitTime;
239
- this.minBytes = options.minBytes;
240
- this.maxBytes = Math.max(options.maxBytes, options.minBytes);
241
- this.maxIdleTime = options.maxIdleTime;
215
+ this.maxBytes = options.maxBytes;
216
+ this.idleTimer = new util_1.Timer(options.maxIdleTime, () => this.flush());
217
+ this.waitTimer = new util_1.Timer(options.maxWaitTime, () => (this.waitTimeouted = true));
242
218
  }
243
219
  async take() {
244
- if (this.state === 'pending') {
245
- this.waitTimeout = setTimeout(() => this._ready('wait'), this.maxWaitTime);
246
- }
247
- await Promise.all([this.readyFuture.promise(), this.putFuture.promise()]);
248
- if (this.state === 'failed') {
249
- throw this.error;
220
+ if (this.isTerminated()) {
221
+ return this.collect();
250
222
  }
251
- let result = this.buffer;
252
- this.buffer = undefined;
253
- if (this.state === 'closed') {
254
- return result;
255
- }
256
- if (result == null) {
257
- throw new Error('Buffer is empty');
258
- }
259
- this.takeFuture.resolve();
260
- this.readyFuture = (0, util_internal_1.createFuture)();
261
- this.putFuture = (0, util_internal_1.createFuture)();
262
- this.takeFuture = (0, util_internal_1.createFuture)();
263
- this.state = 'pending';
223
+ this.waitTimer.start();
224
+ await this.putMutex.wait();
225
+ this.waitTimer.stop();
226
+ let result = this.collect();
227
+ this.putMutex.unready();
228
+ this.takeMutex.ready();
229
+ this.waitTimeouted = false;
264
230
  return result;
265
231
  }
266
- async put(data) {
267
- if (this.state === 'closed' || this.state === 'failed') {
268
- throw new Error('Buffer is closed');
269
- }
270
- if (this.idleTimeout != null) {
271
- clearTimeout(this.idleTimeout);
272
- this.idleTimeout = undefined;
273
- }
274
- if (this.buffer == null) {
275
- this.buffer = { blocks: [], meta: { bytes: 0 } };
232
+ updateHead(head) {
233
+ this.headNumber = head.headNumber;
234
+ this.headUpdated = true;
235
+ if (head.finalizedHeadNumber == null)
236
+ return;
237
+ if (this.finalizedHeadNumber == null || head.finalizedHeadNumber > this.finalizedHeadNumber) {
238
+ this.finalizedHeadNumber = head.finalizedHeadNumber;
239
+ this.finalizedHeadHash = head.finalizedHeadHash;
276
240
  }
277
- this.buffer.blocks.push(...data.blocks);
278
- this.buffer.finalizedHead = data.finalizedHead;
279
- this.buffer.meta.bytes += data.meta.bytes;
280
- this.putFuture.resolve();
281
- if (this.buffer.meta.bytes >= this.minBytes) {
282
- this._ready('minBytes');
241
+ }
242
+ async put(blocks, bytes) {
243
+ if (this.isTerminated()) {
244
+ throw new Error('Buffer is closed');
283
245
  }
284
- if (this.buffer.meta.bytes >= this.maxBytes) {
285
- await this.takeFuture.promise();
246
+ this.idleTimer.stop();
247
+ this.blocks.push(...blocks);
248
+ this.bytes += bytes;
249
+ if (this.waitTimeouted || this.bytes >= this.maxBytes) {
250
+ this.flush();
286
251
  }
287
- if (this.state === 'pending') {
288
- this.idleTimeout = setTimeout(() => this._ready('idle'), this.maxIdleTime);
252
+ if (this.bytes >= this.maxBytes) {
253
+ this.takeMutex.unready();
254
+ await this.takeMutex.wait();
289
255
  }
256
+ this.idleTimer.start();
290
257
  }
291
258
  flush() {
292
- if (this.buffer == null)
259
+ if (!this.hasData())
293
260
  return;
294
- this._ready('flush');
261
+ this.stopTimers();
262
+ this.putMutex.ready();
295
263
  }
296
264
  close() {
297
- if (this.state === 'closed' || this.state === 'failed')
265
+ if (this.isTerminated())
298
266
  return;
299
267
  this.state = 'closed';
300
- this._cleanup();
268
+ this.stopTimers();
269
+ this.putMutex.ready();
270
+ this.takeMutex.reject(new Error('Buffer closed'));
271
+ this.abortController.abort();
301
272
  }
302
273
  fail(err) {
303
- if (this.state === 'closed' || this.state === 'failed')
274
+ if (this.isTerminated())
304
275
  return;
305
276
  this.state = 'failed';
306
277
  this.error = err;
307
- this._cleanup();
278
+ this.stopTimers();
279
+ this.putMutex.ready();
280
+ this.takeMutex.reject(new Error('Buffer closed'));
281
+ this.abortController.abort();
308
282
  }
309
- iterate() {
283
+ [Symbol.asyncIterator]() {
310
284
  return {
311
- [Symbol.asyncIterator]: () => {
312
- return {
313
- next: async () => {
314
- const value = await this.take();
315
- if (value == null) {
316
- return { done: true, value: undefined };
317
- }
318
- return { done: false, value };
319
- },
320
- return: async () => {
321
- this.close();
322
- return { done: true, value: undefined };
323
- },
324
- throw: async (error) => {
325
- this.fail(error);
326
- throw error;
327
- },
328
- };
285
+ next: async () => {
286
+ let value = await this.take();
287
+ if (value == null) {
288
+ return { done: true, value: undefined };
289
+ }
290
+ return { done: false, value };
291
+ },
292
+ return: async () => {
293
+ this.close();
294
+ return { done: true, value: undefined };
295
+ },
296
+ throw: async (error) => {
297
+ this.fail(error);
298
+ throw error;
329
299
  },
330
300
  };
331
301
  }
332
- _ready(reason) {
333
- if (this.state === 'pending') {
334
- this.state = 'ready';
335
- this.readyFuture.resolve();
336
- }
337
- if (this.idleTimeout != null) {
338
- clearTimeout(this.idleTimeout);
339
- this.idleTimeout = undefined;
340
- }
341
- if (this.waitTimeout != null) {
342
- clearTimeout(this.waitTimeout);
343
- this.waitTimeout = undefined;
344
- }
302
+ hasData() {
303
+ return this.blocks.length > 0 || this.headUpdated;
345
304
  }
346
- _cleanup() {
347
- if (this.idleTimeout != null) {
348
- clearTimeout(this.idleTimeout);
349
- this.idleTimeout = undefined;
350
- }
351
- if (this.waitTimeout != null) {
352
- clearTimeout(this.waitTimeout);
353
- this.waitTimeout = undefined;
305
+ isTerminated() {
306
+ return this.state !== 'open';
307
+ }
308
+ isFailed() {
309
+ return this.state === 'failed';
310
+ }
311
+ collect() {
312
+ if (!this.hasData()) {
313
+ if (this.isFailed())
314
+ throw this.error;
315
+ return undefined;
354
316
  }
355
- this.readyFuture.resolve();
356
- this.putFuture.resolve();
357
- this.takeFuture.resolve();
358
- this.abortController.abort();
317
+ let result = {
318
+ blocks: this.blocks,
319
+ meta: {
320
+ bytes: this.bytes,
321
+ headNumber: this.headNumber,
322
+ finalizedHeadNumber: this.finalizedHeadNumber,
323
+ finalizedHeadHash: this.finalizedHeadHash,
324
+ },
325
+ };
326
+ this.blocks = [];
327
+ this.bytes = 0;
328
+ this.headUpdated = false;
329
+ return result;
330
+ }
331
+ stopTimers() {
332
+ this.idleTimer.stop();
333
+ this.waitTimer.stop();
359
334
  }
360
335
  }
361
336
  async function* splitLines(chunks) {
@@ -402,12 +377,19 @@ class LineSplitter {
402
377
  }
403
378
  }
404
379
  class ForkException extends Error {
405
- constructor(previousBlocks, head) {
406
- let parent = (0, util_internal_1.last)(previousBlocks);
407
- super(`expected ${head.number + 1} to have parent ${parent.number}#${parent.hash}, but got ${head.number}#${head.hash}`);
380
+ constructor(blockNumber, parentBlockHash, previousBlocks) {
381
+ let base = (0, util_internal_1.last)(previousBlocks);
382
+ super(`expected block ${blockNumber} to have parent ${base.number}#${parentBlockHash}, ` +
383
+ `but got ${base.number}#${base.hash} as a parent instead`);
384
+ this.blockNumber = blockNumber;
385
+ this.parentBlockHash = parentBlockHash;
408
386
  this.previousBlocks = previousBlocks;
409
- this.head = head;
410
- this.name = 'ForkError';
387
+ }
388
+ get name() {
389
+ return 'ForkException';
390
+ }
391
+ get isSubsquidForkException() {
392
+ return true;
411
393
  }
412
394
  }
413
395
  exports.ForkException = ForkException;
@@ -418,15 +400,15 @@ function isForkException(err) {
418
400
  return true;
419
401
  return false;
420
402
  }
421
- function getFinalizedHeadHeader(headers) {
422
- let finalizedHeadHash = headers.get('X-Sqd-Finalized-Head-Hash');
423
- let finalizedHeadNumber = headers.get('X-Sqd-Finalized-Head-Number');
424
- return finalizedHeadHash != null && finalizedHeadNumber != null
425
- ? {
426
- hash: finalizedHeadHash,
427
- number: parseInt(finalizedHeadNumber),
428
- }
429
- : undefined;
403
+ function getPortalStreamHeaders(headers) {
404
+ let finalizedHeadHash = headers.get('x-sqd-finalized-head-hash');
405
+ let finalizedHeadNumber = headers.get('x-sqd-finalized-head-number');
406
+ let headNumber = headers.get('x-sqd-head-number');
407
+ return {
408
+ headNumber: headNumber ? parseInt(headNumber) : undefined,
409
+ finalizedHeadNumber: finalizedHeadNumber ? parseInt(finalizedHeadNumber) : undefined,
410
+ finalizedHeadHash: finalizedHeadHash ?? undefined,
411
+ };
430
412
  }
431
413
  function isStreamAbortedError(err) {
432
414
  if (!(err instanceof Error))