@pezkuwi/rpc-provider 16.5.5 → 16.5.6

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 (125) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +10 -10
  3. package/bizinikiwi-connect/Health.js +259 -0
  4. package/{build/substrate-connect → bizinikiwi-connect}/index.d.ts +3 -3
  5. package/bizinikiwi-connect/index.js +319 -0
  6. package/{build/bundle.d.ts → bundle.d.ts} +1 -1
  7. package/{src/bundle.ts → bundle.js} +1 -4
  8. package/cjs/bizinikiwi-connect/Health.d.ts +7 -0
  9. package/cjs/bizinikiwi-connect/Health.js +264 -0
  10. package/cjs/bizinikiwi-connect/index.d.ts +22 -0
  11. package/cjs/bizinikiwi-connect/index.js +323 -0
  12. package/cjs/bizinikiwi-connect/types.d.ts +12 -0
  13. package/cjs/bizinikiwi-connect/types.js +2 -0
  14. package/cjs/bundle.d.ts +5 -0
  15. package/cjs/bundle.js +14 -0
  16. package/cjs/coder/error.js +53 -0
  17. package/cjs/coder/index.js +63 -0
  18. package/cjs/defaults.js +8 -0
  19. package/{build → cjs}/http/index.d.ts +1 -1
  20. package/cjs/http/index.js +196 -0
  21. package/cjs/http/types.js +2 -0
  22. package/cjs/index.js +5 -0
  23. package/cjs/lru.js +150 -0
  24. package/cjs/mock/index.js +196 -0
  25. package/cjs/mock/mockHttp.js +17 -0
  26. package/cjs/mock/mockWs.js +47 -0
  27. package/cjs/mock/types.js +2 -0
  28. package/cjs/package.json +3 -0
  29. package/cjs/packageDetect.d.ts +1 -0
  30. package/cjs/packageDetect.js +6 -0
  31. package/cjs/packageInfo.js +4 -0
  32. package/cjs/types.js +2 -0
  33. package/cjs/ws/errors.js +41 -0
  34. package/{build → cjs}/ws/index.d.ts +1 -1
  35. package/cjs/ws/index.js +529 -0
  36. package/coder/error.d.ts +29 -0
  37. package/coder/error.js +50 -0
  38. package/coder/index.d.ts +8 -0
  39. package/coder/index.js +58 -0
  40. package/defaults.d.ts +5 -0
  41. package/defaults.js +6 -0
  42. package/http/index.d.ts +81 -0
  43. package/http/index.js +191 -0
  44. package/http/types.d.ts +7 -0
  45. package/http/types.js +1 -0
  46. package/index.d.ts +2 -0
  47. package/index.js +2 -0
  48. package/lru.d.ts +15 -0
  49. package/lru.js +146 -0
  50. package/mock/index.d.ts +35 -0
  51. package/mock/index.js +191 -0
  52. package/mock/mockHttp.d.ts +9 -0
  53. package/mock/mockHttp.js +12 -0
  54. package/mock/mockWs.d.ts +26 -0
  55. package/mock/mockWs.js +43 -0
  56. package/mock/types.d.ts +23 -0
  57. package/mock/types.js +1 -0
  58. package/package.json +316 -15
  59. package/packageDetect.d.ts +1 -0
  60. package/packageDetect.js +4 -0
  61. package/packageInfo.d.ts +6 -0
  62. package/packageInfo.js +1 -0
  63. package/types.d.ts +85 -0
  64. package/types.js +1 -0
  65. package/ws/errors.d.ts +1 -0
  66. package/ws/errors.js +38 -0
  67. package/ws/index.d.ts +121 -0
  68. package/ws/index.js +524 -0
  69. package/src/coder/decodeResponse.spec.ts +0 -70
  70. package/src/coder/encodeJson.spec.ts +0 -20
  71. package/src/coder/encodeObject.spec.ts +0 -25
  72. package/src/coder/error.spec.ts +0 -111
  73. package/src/coder/error.ts +0 -66
  74. package/src/coder/index.ts +0 -88
  75. package/src/defaults.ts +0 -10
  76. package/src/http/index.spec.ts +0 -72
  77. package/src/http/index.ts +0 -238
  78. package/src/http/send.spec.ts +0 -61
  79. package/src/http/types.ts +0 -11
  80. package/src/index.ts +0 -6
  81. package/src/lru.spec.ts +0 -74
  82. package/src/lru.ts +0 -197
  83. package/src/mock/index.ts +0 -259
  84. package/src/mock/mockHttp.ts +0 -35
  85. package/src/mock/mockWs.ts +0 -92
  86. package/src/mock/on.spec.ts +0 -43
  87. package/src/mock/send.spec.ts +0 -38
  88. package/src/mock/subscribe.spec.ts +0 -81
  89. package/src/mock/types.ts +0 -36
  90. package/src/mock/unsubscribe.spec.ts +0 -57
  91. package/src/mod.ts +0 -4
  92. package/src/packageDetect.ts +0 -12
  93. package/src/packageInfo.ts +0 -6
  94. package/src/substrate-connect/Health.ts +0 -325
  95. package/src/substrate-connect/index.spec.ts +0 -638
  96. package/src/substrate-connect/index.ts +0 -415
  97. package/src/substrate-connect/types.ts +0 -16
  98. package/src/types.ts +0 -101
  99. package/src/ws/connect.spec.ts +0 -167
  100. package/src/ws/errors.ts +0 -41
  101. package/src/ws/index.spec.ts +0 -97
  102. package/src/ws/index.ts +0 -652
  103. package/src/ws/send.spec.ts +0 -126
  104. package/src/ws/state.spec.ts +0 -20
  105. package/src/ws/subscribe.spec.ts +0 -68
  106. package/src/ws/unsubscribe.spec.ts +0 -100
  107. package/tsconfig.build.json +0 -17
  108. package/tsconfig.build.tsbuildinfo +0 -1
  109. package/tsconfig.spec.json +0 -18
  110. /package/{build/substrate-connect → bizinikiwi-connect}/Health.d.ts +0 -0
  111. /package/{build/substrate-connect → bizinikiwi-connect}/types.d.ts +0 -0
  112. /package/{build/packageDetect.d.ts → bizinikiwi-connect/types.js} +0 -0
  113. /package/{build → cjs}/coder/error.d.ts +0 -0
  114. /package/{build → cjs}/coder/index.d.ts +0 -0
  115. /package/{build → cjs}/defaults.d.ts +0 -0
  116. /package/{build → cjs}/http/types.d.ts +0 -0
  117. /package/{build → cjs}/index.d.ts +0 -0
  118. /package/{build → cjs}/lru.d.ts +0 -0
  119. /package/{build → cjs}/mock/index.d.ts +0 -0
  120. /package/{build → cjs}/mock/mockHttp.d.ts +0 -0
  121. /package/{build → cjs}/mock/mockWs.d.ts +0 -0
  122. /package/{build → cjs}/mock/types.d.ts +0 -0
  123. /package/{build → cjs}/packageInfo.d.ts +0 -0
  124. /package/{build → cjs}/types.d.ts +0 -0
  125. /package/{build → cjs}/ws/errors.d.ts +0 -0
@@ -1,325 +0,0 @@
1
- // Copyright 2017-2025 @polkadot/rpc-provider authors & contributors
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- import type { HealthChecker, SmoldotHealth } from './types.js';
5
-
6
- import { stringify } from '@pezkuwi/util';
7
-
8
- interface JSONRequest {
9
- id: string;
10
- jsonrpc: '2.0',
11
- method: string;
12
- params: unknown[];
13
- }
14
-
15
- /*
16
- * Creates a new health checker.
17
- *
18
- * The role of the health checker is to report to the user the health of a smoldot chain.
19
- *
20
- * In order to use it, start by creating a health checker, and call `setSendJsonRpc` to set the
21
- * way to send a JSON-RPC request to a chain. The health checker is disabled by default. Use
22
- * `start()` in order to start the health checks. The `start()` function must be passed a callback called
23
- * when an update to the health of the node is available.
24
- *
25
- * In order to send a JSON-RPC request to the chain, you **must** use the `sendJsonRpc` function
26
- * of the health checker. The health checker rewrites the `id` of the requests it receives.
27
- *
28
- * When the chain send a JSON-RPC response, it must be passed to `responsePassThrough()`. This
29
- * function intercepts the responses destined to the requests that have been emitted by the health
30
- * checker and returns `null`. If the response doesn't concern the health checker, the response is
31
- * simply returned by the function.
32
- *
33
- * # How it works
34
- *
35
- * The health checker periodically calls the `system_health` JSON-RPC call in order to determine
36
- * the health of the chain.
37
- *
38
- * In addition to this, as long as the health check reports that `isSyncing` is `true`, the
39
- * health checker also maintains a subscription to new best blocks using `chain_subscribeNewHeads`.
40
- * Whenever a new block is notified, a health check is performed immediately in order to determine
41
- * whether `isSyncing` has changed to `false`.
42
- *
43
- * Thanks to this subscription, the latency of the report of the switch from `isSyncing: true` to
44
- * `isSyncing: false` is very low.
45
- *
46
- */
47
- export function healthChecker (): HealthChecker {
48
- // `null` if health checker is not started.
49
- let checker: null | InnerChecker = null;
50
- let sendJsonRpc: null | ((request: string) => void) = null;
51
-
52
- return {
53
- responsePassThrough: (jsonRpcResponse) => {
54
- if (checker === null) {
55
- return jsonRpcResponse;
56
- }
57
-
58
- return checker.responsePassThrough(jsonRpcResponse);
59
- },
60
- sendJsonRpc: (request) => {
61
- if (!sendJsonRpc) {
62
- throw new Error('setSendJsonRpc must be called before sending requests');
63
- }
64
-
65
- if (checker === null) {
66
- sendJsonRpc(request);
67
- } else {
68
- checker.sendJsonRpc(request);
69
- }
70
- },
71
- setSendJsonRpc: (cb) => {
72
- sendJsonRpc = cb;
73
- },
74
- start: (healthCallback) => {
75
- if (checker !== null) {
76
- throw new Error("Can't start the health checker multiple times in parallel");
77
- } else if (!sendJsonRpc) {
78
- throw new Error('setSendJsonRpc must be called before starting the health checks');
79
- }
80
-
81
- checker = new InnerChecker(healthCallback, sendJsonRpc);
82
- checker.update(true);
83
- },
84
- stop: () => {
85
- if (checker === null) {
86
- return;
87
- } // Already stopped.
88
-
89
- checker.destroy();
90
- checker = null;
91
- }
92
- };
93
- }
94
-
95
- class InnerChecker {
96
- #healthCallback: (health: SmoldotHealth) => void;
97
- #currentHealthCheckId: string | null = null;
98
- #currentHealthTimeout: ReturnType<typeof setTimeout> | null = null;
99
- #currentSubunsubRequestId: string | null = null;
100
- #currentSubscriptionId: string | null = null;
101
- #requestToSmoldot: (request: JSONRequest) => void;
102
- #isSyncing = false;
103
- #nextRequestId = 0;
104
-
105
- constructor (healthCallback: (health: SmoldotHealth) => void, requestToSmoldot: (request: string) => void) {
106
- this.#healthCallback = healthCallback;
107
- this.#requestToSmoldot = (request: JSONRequest) => requestToSmoldot(stringify(request));
108
- }
109
-
110
- sendJsonRpc = (request: string): void => {
111
- // Replace the `id` in the request to prefix the request ID with `extern:`.
112
- let parsedRequest: JSONRequest;
113
-
114
- try {
115
- parsedRequest = JSON.parse(request) as JSONRequest;
116
- } catch {
117
- return;
118
- }
119
-
120
- if (parsedRequest.id) {
121
- const newId = 'extern:' + stringify(parsedRequest.id);
122
-
123
- parsedRequest.id = newId;
124
- }
125
-
126
- this.#requestToSmoldot(parsedRequest);
127
- };
128
-
129
- responsePassThrough = (jsonRpcResponse: string): string | null => {
130
- let parsedResponse: {id: string, result?: SmoldotHealth, params?: { subscription: string }};
131
-
132
- try {
133
- parsedResponse = JSON.parse(jsonRpcResponse) as { id: string, result?: SmoldotHealth };
134
- } catch {
135
- return jsonRpcResponse;
136
- }
137
-
138
- // Check whether response is a response to `system_health`.
139
- if (parsedResponse.id && this.#currentHealthCheckId === parsedResponse.id) {
140
- this.#currentHealthCheckId = null;
141
-
142
- // Check whether query was successful. It is possible for queries to fail for
143
- // various reasons, such as the client being overloaded.
144
- if (!parsedResponse.result) {
145
- this.update(false);
146
-
147
- return null;
148
- }
149
-
150
- this.#healthCallback(parsedResponse.result);
151
- this.#isSyncing = parsedResponse.result.isSyncing;
152
- this.update(false);
153
-
154
- return null;
155
- }
156
-
157
- // Check whether response is a response to the subscription or unsubscription.
158
- if (
159
- parsedResponse.id &&
160
- this.#currentSubunsubRequestId === parsedResponse.id
161
- ) {
162
- this.#currentSubunsubRequestId = null;
163
-
164
- // Check whether query was successful. It is possible for queries to fail for
165
- // various reasons, such as the client being overloaded.
166
- if (!parsedResponse.result) {
167
- this.update(false);
168
-
169
- return null;
170
- }
171
-
172
- if (this.#currentSubscriptionId) {
173
- this.#currentSubscriptionId = null;
174
- } else {
175
- this.#currentSubscriptionId = parsedResponse.result as unknown as string;
176
- }
177
-
178
- this.update(false);
179
-
180
- return null;
181
- }
182
-
183
- // Check whether response is a notification to a subscription.
184
- if (
185
- parsedResponse.params &&
186
- this.#currentSubscriptionId &&
187
- parsedResponse.params.subscription === this.#currentSubscriptionId
188
- ) {
189
- // Note that after a successful subscription, a notification containing
190
- // the current best block is always returned. Considering that a
191
- // subscription is performed in response to a health check, calling
192
- // `startHealthCheck()` here will lead to a second health check.
193
- // It might seem redundant to perform two health checks in a quick
194
- // succession, but doing so doesn't lead to any problem, and it is
195
- // actually possible for the health to have changed in between as the
196
- // current best block might have been updated during the subscription
197
- // request.
198
- this.update(true);
199
-
200
- return null;
201
- }
202
-
203
- // Response doesn't concern us.
204
- if (parsedResponse.id) {
205
- const id: string = parsedResponse.id;
206
-
207
- // Need to remove the `extern:` prefix.
208
- if (!id.startsWith('extern:')) {
209
- throw new Error('State inconsistency in health checker');
210
- }
211
-
212
- const newId = JSON.parse(id.slice('extern:'.length)) as string;
213
-
214
- parsedResponse.id = newId;
215
- }
216
-
217
- return stringify(parsedResponse);
218
- };
219
-
220
- update = (startNow: boolean): void => {
221
- // If `startNow`, clear `#currentHealthTimeout` so that it is set below.
222
- if (startNow && this.#currentHealthTimeout) {
223
- clearTimeout(this.#currentHealthTimeout);
224
- this.#currentHealthTimeout = null;
225
- }
226
-
227
- if (!this.#currentHealthTimeout) {
228
- const startHealthRequest = () => {
229
- this.#currentHealthTimeout = null;
230
-
231
- // No matter what, don't start a health request if there is already one in progress.
232
- // This is sane to do because receiving a response to a health request calls `update()`.
233
- if (this.#currentHealthCheckId) {
234
- return;
235
- }
236
-
237
- // Actual request starting.
238
- this.#currentHealthCheckId = `health-checker:${this.#nextRequestId}`;
239
- this.#nextRequestId += 1;
240
-
241
- this.#requestToSmoldot({
242
- id: this.#currentHealthCheckId,
243
- jsonrpc: '2.0',
244
- method: 'system_health',
245
- params: []
246
- });
247
- };
248
-
249
- if (startNow) {
250
- startHealthRequest();
251
- } else {
252
- this.#currentHealthTimeout = setTimeout(startHealthRequest, 1000);
253
- }
254
- }
255
-
256
- if (
257
- this.#isSyncing &&
258
- !this.#currentSubscriptionId &&
259
- !this.#currentSubunsubRequestId
260
- ) {
261
- this.startSubscription();
262
- }
263
-
264
- if (
265
- !this.#isSyncing &&
266
- this.#currentSubscriptionId &&
267
- !this.#currentSubunsubRequestId
268
- ) {
269
- this.endSubscription();
270
- }
271
- };
272
-
273
- startSubscription = (): void => {
274
- if (this.#currentSubunsubRequestId || this.#currentSubscriptionId) {
275
- throw new Error('Internal error in health checker');
276
- }
277
-
278
- this.#currentSubunsubRequestId = `health-checker:${this.#nextRequestId}`;
279
- this.#nextRequestId += 1;
280
-
281
- this.#requestToSmoldot({
282
- id: this.#currentSubunsubRequestId,
283
- jsonrpc: '2.0',
284
- method: 'chain_subscribeNewHeads',
285
- params: []
286
- });
287
- };
288
-
289
- endSubscription = (): void => {
290
- if (this.#currentSubunsubRequestId || !this.#currentSubscriptionId) {
291
- throw new Error('Internal error in health checker');
292
- }
293
-
294
- this.#currentSubunsubRequestId = `health-checker:${this.#nextRequestId}`;
295
- this.#nextRequestId += 1;
296
-
297
- this.#requestToSmoldot({
298
- id: this.#currentSubunsubRequestId,
299
- jsonrpc: '2.0',
300
- method: 'chain_unsubscribeNewHeads',
301
- params: [this.#currentSubscriptionId]
302
- });
303
- };
304
-
305
- destroy = (): void => {
306
- if (this.#currentHealthTimeout) {
307
- clearTimeout(this.#currentHealthTimeout);
308
- this.#currentHealthTimeout = null;
309
- }
310
- };
311
- }
312
-
313
- export class HealthCheckError extends Error {
314
- readonly #cause: unknown;
315
-
316
- getCause (): unknown {
317
- return this.#cause;
318
- }
319
-
320
- constructor (response: unknown, message = 'Got error response asking for system health') {
321
- super(message);
322
-
323
- this.#cause = response;
324
- }
325
- }