@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.
- package/LICENSE +201 -0
- package/README.md +10 -10
- package/bizinikiwi-connect/Health.js +259 -0
- package/{build/substrate-connect → bizinikiwi-connect}/index.d.ts +3 -3
- package/bizinikiwi-connect/index.js +319 -0
- package/{build/bundle.d.ts → bundle.d.ts} +1 -1
- package/{src/bundle.ts → bundle.js} +1 -4
- package/cjs/bizinikiwi-connect/Health.d.ts +7 -0
- package/cjs/bizinikiwi-connect/Health.js +264 -0
- package/cjs/bizinikiwi-connect/index.d.ts +22 -0
- package/cjs/bizinikiwi-connect/index.js +323 -0
- package/cjs/bizinikiwi-connect/types.d.ts +12 -0
- package/cjs/bizinikiwi-connect/types.js +2 -0
- package/cjs/bundle.d.ts +5 -0
- package/cjs/bundle.js +14 -0
- package/cjs/coder/error.js +53 -0
- package/cjs/coder/index.js +63 -0
- package/cjs/defaults.js +8 -0
- package/{build → cjs}/http/index.d.ts +1 -1
- package/cjs/http/index.js +196 -0
- package/cjs/http/types.js +2 -0
- package/cjs/index.js +5 -0
- package/cjs/lru.js +150 -0
- package/cjs/mock/index.js +196 -0
- package/cjs/mock/mockHttp.js +17 -0
- package/cjs/mock/mockWs.js +47 -0
- package/cjs/mock/types.js +2 -0
- package/cjs/package.json +3 -0
- package/cjs/packageDetect.d.ts +1 -0
- package/cjs/packageDetect.js +6 -0
- package/cjs/packageInfo.js +4 -0
- package/cjs/types.js +2 -0
- package/cjs/ws/errors.js +41 -0
- package/{build → cjs}/ws/index.d.ts +1 -1
- package/cjs/ws/index.js +529 -0
- package/coder/error.d.ts +29 -0
- package/coder/error.js +50 -0
- package/coder/index.d.ts +8 -0
- package/coder/index.js +58 -0
- package/defaults.d.ts +5 -0
- package/defaults.js +6 -0
- package/http/index.d.ts +81 -0
- package/http/index.js +191 -0
- package/http/types.d.ts +7 -0
- package/http/types.js +1 -0
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/lru.d.ts +15 -0
- package/lru.js +146 -0
- package/mock/index.d.ts +35 -0
- package/mock/index.js +191 -0
- package/mock/mockHttp.d.ts +9 -0
- package/mock/mockHttp.js +12 -0
- package/mock/mockWs.d.ts +26 -0
- package/mock/mockWs.js +43 -0
- package/mock/types.d.ts +23 -0
- package/mock/types.js +1 -0
- package/package.json +316 -15
- package/packageDetect.d.ts +1 -0
- package/packageDetect.js +4 -0
- package/packageInfo.d.ts +6 -0
- package/packageInfo.js +1 -0
- package/types.d.ts +85 -0
- package/types.js +1 -0
- package/ws/errors.d.ts +1 -0
- package/ws/errors.js +38 -0
- package/ws/index.d.ts +121 -0
- package/ws/index.js +524 -0
- package/src/coder/decodeResponse.spec.ts +0 -70
- package/src/coder/encodeJson.spec.ts +0 -20
- package/src/coder/encodeObject.spec.ts +0 -25
- package/src/coder/error.spec.ts +0 -111
- package/src/coder/error.ts +0 -66
- package/src/coder/index.ts +0 -88
- package/src/defaults.ts +0 -10
- package/src/http/index.spec.ts +0 -72
- package/src/http/index.ts +0 -238
- package/src/http/send.spec.ts +0 -61
- package/src/http/types.ts +0 -11
- package/src/index.ts +0 -6
- package/src/lru.spec.ts +0 -74
- package/src/lru.ts +0 -197
- package/src/mock/index.ts +0 -259
- package/src/mock/mockHttp.ts +0 -35
- package/src/mock/mockWs.ts +0 -92
- package/src/mock/on.spec.ts +0 -43
- package/src/mock/send.spec.ts +0 -38
- package/src/mock/subscribe.spec.ts +0 -81
- package/src/mock/types.ts +0 -36
- package/src/mock/unsubscribe.spec.ts +0 -57
- package/src/mod.ts +0 -4
- package/src/packageDetect.ts +0 -12
- package/src/packageInfo.ts +0 -6
- package/src/substrate-connect/Health.ts +0 -325
- package/src/substrate-connect/index.spec.ts +0 -638
- package/src/substrate-connect/index.ts +0 -415
- package/src/substrate-connect/types.ts +0 -16
- package/src/types.ts +0 -101
- package/src/ws/connect.spec.ts +0 -167
- package/src/ws/errors.ts +0 -41
- package/src/ws/index.spec.ts +0 -97
- package/src/ws/index.ts +0 -652
- package/src/ws/send.spec.ts +0 -126
- package/src/ws/state.spec.ts +0 -20
- package/src/ws/subscribe.spec.ts +0 -68
- package/src/ws/unsubscribe.spec.ts +0 -100
- package/tsconfig.build.json +0 -17
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.spec.json +0 -18
- /package/{build/substrate-connect → bizinikiwi-connect}/Health.d.ts +0 -0
- /package/{build/substrate-connect → bizinikiwi-connect}/types.d.ts +0 -0
- /package/{build/packageDetect.d.ts → bizinikiwi-connect/types.js} +0 -0
- /package/{build → cjs}/coder/error.d.ts +0 -0
- /package/{build → cjs}/coder/index.d.ts +0 -0
- /package/{build → cjs}/defaults.d.ts +0 -0
- /package/{build → cjs}/http/types.d.ts +0 -0
- /package/{build → cjs}/index.d.ts +0 -0
- /package/{build → cjs}/lru.d.ts +0 -0
- /package/{build → cjs}/mock/index.d.ts +0 -0
- /package/{build → cjs}/mock/mockHttp.d.ts +0 -0
- /package/{build → cjs}/mock/mockWs.d.ts +0 -0
- /package/{build → cjs}/mock/types.d.ts +0 -0
- /package/{build → cjs}/packageInfo.d.ts +0 -0
- /package/{build → cjs}/types.d.ts +0 -0
- /package/{build → cjs}/ws/errors.d.ts +0 -0
|
@@ -1,638 +0,0 @@
|
|
|
1
|
-
// Copyright 2017-2025 @polkadot/rpc-provider authors & contributors
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
|
|
4
|
-
/// <reference types="@pezkuwi/dev-test/globals.d.ts" />
|
|
5
|
-
|
|
6
|
-
import type * as Sc from '@substrate/connect';
|
|
7
|
-
import type { HealthChecker, SmoldotHealth } from './types.js';
|
|
8
|
-
|
|
9
|
-
import { noop, stringify } from '@pezkuwi/util';
|
|
10
|
-
|
|
11
|
-
import { ScProvider } from './index.js';
|
|
12
|
-
|
|
13
|
-
interface MockChain extends Sc.Chain {
|
|
14
|
-
_spec: () => string;
|
|
15
|
-
_recevedRequests: () => string[];
|
|
16
|
-
_isTerminated: () => boolean;
|
|
17
|
-
_triggerCallback: (response: string | object) => void;
|
|
18
|
-
_setTerminateInterceptor: (fn: () => void) => void;
|
|
19
|
-
_setSendJsonRpcInterceptor: (fn: (rpc: string) => void) => void;
|
|
20
|
-
_getLatestRequest: () => string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface MockedHealthChecker extends HealthChecker {
|
|
24
|
-
_isActive: () => boolean;
|
|
25
|
-
_triggerHealthUpdate: (update: SmoldotHealth) => void;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
type MockSc = typeof Sc & {
|
|
29
|
-
latestChain: () => MockChain;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
enum WellKnownChain {
|
|
33
|
-
polkadot = 'polkadot',
|
|
34
|
-
ksmcc3 = 'ksmcc3',
|
|
35
|
-
rococo_v2_2 = 'rococo_v2_2',
|
|
36
|
-
westend2 = 'westend2'
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const wait = (ms: number) =>
|
|
40
|
-
new Promise((resolve) =>
|
|
41
|
-
setTimeout(resolve, ms)
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
function healthCheckerMock (): MockedHealthChecker {
|
|
45
|
-
let cb: (health: SmoldotHealth) => void = () => undefined;
|
|
46
|
-
let sendJsonRpc: (request: string) => void = () => undefined;
|
|
47
|
-
let isActive = false;
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
_isActive: () => isActive,
|
|
51
|
-
_triggerHealthUpdate: (update: SmoldotHealth) => {
|
|
52
|
-
cb(update);
|
|
53
|
-
},
|
|
54
|
-
responsePassThrough: (response) => response,
|
|
55
|
-
sendJsonRpc: (...args) => sendJsonRpc(...args),
|
|
56
|
-
setSendJsonRpc: (cb) => {
|
|
57
|
-
sendJsonRpc = cb;
|
|
58
|
-
},
|
|
59
|
-
start: (x) => {
|
|
60
|
-
isActive = true;
|
|
61
|
-
cb = x;
|
|
62
|
-
},
|
|
63
|
-
stop: () => {
|
|
64
|
-
isActive = false;
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function healthCheckerFactory () {
|
|
70
|
-
const _healthCheckers: MockedHealthChecker[] = [];
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
_healthCheckers,
|
|
74
|
-
_latestHealthChecker: () => _healthCheckers.slice(-1)[0],
|
|
75
|
-
healthChecker: () => {
|
|
76
|
-
const result = healthCheckerMock();
|
|
77
|
-
|
|
78
|
-
_healthCheckers.push(result);
|
|
79
|
-
|
|
80
|
-
return result;
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function getFakeChain (spec: string, callback: Sc.JsonRpcCallback): MockChain {
|
|
86
|
-
const _receivedRequests: string[] = [];
|
|
87
|
-
let _isTerminated = false;
|
|
88
|
-
|
|
89
|
-
let terminateInterceptor = Function.prototype;
|
|
90
|
-
let sendJsonRpcInterceptor = Function.prototype;
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
_getLatestRequest: () => _receivedRequests[_receivedRequests.length - 1],
|
|
94
|
-
_isTerminated: () => _isTerminated,
|
|
95
|
-
_recevedRequests: () => _receivedRequests,
|
|
96
|
-
_setSendJsonRpcInterceptor: (fn) => {
|
|
97
|
-
sendJsonRpcInterceptor = fn;
|
|
98
|
-
},
|
|
99
|
-
_setTerminateInterceptor: (fn) => {
|
|
100
|
-
terminateInterceptor = fn;
|
|
101
|
-
},
|
|
102
|
-
_spec: () => spec,
|
|
103
|
-
_triggerCallback: (response) => {
|
|
104
|
-
callback(
|
|
105
|
-
typeof response === 'string'
|
|
106
|
-
? response
|
|
107
|
-
: stringify(response)
|
|
108
|
-
);
|
|
109
|
-
},
|
|
110
|
-
addChain: (chainSpec, jsonRpcCallback) =>
|
|
111
|
-
Promise.resolve(getFakeChain(chainSpec, jsonRpcCallback ?? noop)),
|
|
112
|
-
remove: () => {
|
|
113
|
-
terminateInterceptor();
|
|
114
|
-
_isTerminated = true;
|
|
115
|
-
},
|
|
116
|
-
sendJsonRpc: (rpc) => {
|
|
117
|
-
sendJsonRpcInterceptor(rpc);
|
|
118
|
-
_receivedRequests.push(rpc);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function getFakeClient () {
|
|
124
|
-
const chains: MockChain[] = [];
|
|
125
|
-
let addChainInterceptor: Promise<void> = Promise.resolve();
|
|
126
|
-
let addWellKnownChainInterceptor: Promise<void> = Promise.resolve();
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
_chains: () => chains,
|
|
130
|
-
_setAddChainInterceptor: (interceptor: Promise<void>) => {
|
|
131
|
-
addChainInterceptor = interceptor;
|
|
132
|
-
},
|
|
133
|
-
_setAddWellKnownChainInterceptor: (interceptor: Promise<void>) => {
|
|
134
|
-
addWellKnownChainInterceptor = interceptor;
|
|
135
|
-
},
|
|
136
|
-
addChain: (chainSpec: string, cb: Sc.JsonRpcCallback): Promise<MockChain> =>
|
|
137
|
-
addChainInterceptor.then(() => {
|
|
138
|
-
const result = getFakeChain(chainSpec, cb);
|
|
139
|
-
|
|
140
|
-
chains.push(result);
|
|
141
|
-
|
|
142
|
-
return result;
|
|
143
|
-
}),
|
|
144
|
-
addWellKnownChain: (
|
|
145
|
-
wellKnownChain: string,
|
|
146
|
-
cb: Sc.JsonRpcCallback
|
|
147
|
-
): Promise<MockChain> =>
|
|
148
|
-
addWellKnownChainInterceptor.then(() => {
|
|
149
|
-
const result = getFakeChain(wellKnownChain, cb);
|
|
150
|
-
|
|
151
|
-
chains.push(result);
|
|
152
|
-
|
|
153
|
-
return result;
|
|
154
|
-
})
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function connectorFactory (): MockSc {
|
|
159
|
-
const clients: ReturnType<typeof getFakeClient>[] = [];
|
|
160
|
-
const latestClient = () => clients[clients.length - 1];
|
|
161
|
-
|
|
162
|
-
return {
|
|
163
|
-
WellKnownChain,
|
|
164
|
-
_clients: () => clients,
|
|
165
|
-
createScClient: () => {
|
|
166
|
-
const result = getFakeClient();
|
|
167
|
-
|
|
168
|
-
clients.push(result);
|
|
169
|
-
|
|
170
|
-
return result;
|
|
171
|
-
},
|
|
172
|
-
latestChain: () =>
|
|
173
|
-
latestClient()._chains()[latestClient()._chains().length - 1],
|
|
174
|
-
latestClient
|
|
175
|
-
} as unknown as MockSc;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function setChainSyncyingStatus (isSyncing: boolean): void {
|
|
179
|
-
getCurrentHealthChecker()._triggerHealthUpdate({
|
|
180
|
-
isSyncing,
|
|
181
|
-
peers: 1,
|
|
182
|
-
shouldHavePeers: true
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
let mockSc: MockSc;
|
|
187
|
-
let mockedHealthChecker: ReturnType<typeof healthCheckerFactory>;
|
|
188
|
-
const getCurrentHealthChecker = () => mockedHealthChecker._latestHealthChecker();
|
|
189
|
-
|
|
190
|
-
describe('ScProvider', () => {
|
|
191
|
-
beforeAll(() => {
|
|
192
|
-
mockSc = connectorFactory();
|
|
193
|
-
mockedHealthChecker = healthCheckerFactory();
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
describe('on', () => {
|
|
197
|
-
it('emits `connected` as soon as the chain is not syncing', async () => {
|
|
198
|
-
const provider = new ScProvider(mockSc, '');
|
|
199
|
-
|
|
200
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
201
|
-
|
|
202
|
-
const onConnected = jest.fn();
|
|
203
|
-
|
|
204
|
-
provider.on('connected', onConnected);
|
|
205
|
-
|
|
206
|
-
expect(onConnected).not.toHaveBeenCalled();
|
|
207
|
-
setChainSyncyingStatus(false);
|
|
208
|
-
expect(onConnected).toHaveBeenCalled();
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it('stops receiving notifications after unsubscribing', async () => {
|
|
212
|
-
const provider = new ScProvider(mockSc, '');
|
|
213
|
-
|
|
214
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
215
|
-
|
|
216
|
-
const onConnected = jest.fn();
|
|
217
|
-
|
|
218
|
-
provider.on('connected', onConnected)();
|
|
219
|
-
expect(onConnected).not.toHaveBeenCalled();
|
|
220
|
-
|
|
221
|
-
setChainSyncyingStatus(false);
|
|
222
|
-
expect(onConnected).not.toHaveBeenCalled();
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it('synchronously emits connected if the Provider is already `connected`', async () => {
|
|
226
|
-
const provider = new ScProvider(mockSc, '');
|
|
227
|
-
|
|
228
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
229
|
-
|
|
230
|
-
setChainSyncyingStatus(false);
|
|
231
|
-
|
|
232
|
-
const onConnected = jest.fn();
|
|
233
|
-
|
|
234
|
-
provider.on('connected', onConnected);
|
|
235
|
-
expect(onConnected).toHaveBeenCalled();
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it('emits `disconnected` once the chain goes back to syncing', async () => {
|
|
239
|
-
const provider = new ScProvider(mockSc, '');
|
|
240
|
-
|
|
241
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
242
|
-
|
|
243
|
-
setChainSyncyingStatus(false);
|
|
244
|
-
|
|
245
|
-
const onConnected = jest.fn();
|
|
246
|
-
const onDisconnected = jest.fn();
|
|
247
|
-
|
|
248
|
-
provider.on('connected', onConnected);
|
|
249
|
-
provider.on('disconnected', onDisconnected);
|
|
250
|
-
|
|
251
|
-
expect(onConnected).toHaveBeenCalled();
|
|
252
|
-
expect(onDisconnected).not.toHaveBeenCalled();
|
|
253
|
-
|
|
254
|
-
onConnected.mockReset();
|
|
255
|
-
setChainSyncyingStatus(true);
|
|
256
|
-
|
|
257
|
-
expect(onConnected).not.toHaveBeenCalled();
|
|
258
|
-
expect(onDisconnected).toHaveBeenCalled();
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
describe('hasSubscriptions', () => {
|
|
263
|
-
it('supports subscriptions', async () => {
|
|
264
|
-
const provider = new ScProvider(mockSc, '');
|
|
265
|
-
|
|
266
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
267
|
-
|
|
268
|
-
expect(provider.hasSubscriptions).toBe(true);
|
|
269
|
-
});
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
describe('clone', () => {
|
|
273
|
-
it('can not be clonned', async () => {
|
|
274
|
-
const provider = new ScProvider(mockSc, '');
|
|
275
|
-
|
|
276
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
277
|
-
|
|
278
|
-
expect(() => provider.clone()).toThrow();
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
describe('connect', () => {
|
|
283
|
-
it('does not create a new chain when trying to re-connect while the current chain is syncing', async () => {
|
|
284
|
-
const provider = new ScProvider(mockSc, '');
|
|
285
|
-
|
|
286
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
287
|
-
const chain = mockSc.latestChain();
|
|
288
|
-
|
|
289
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
290
|
-
expect(chain).toBe(mockSc.latestChain());
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
it('throws when trying to connect on an already connected Provider', async () => {
|
|
294
|
-
const provider = new ScProvider(mockSc, '');
|
|
295
|
-
|
|
296
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
297
|
-
|
|
298
|
-
setChainSyncyingStatus(false);
|
|
299
|
-
|
|
300
|
-
await expect(
|
|
301
|
-
provider.connect(undefined, mockedHealthChecker.healthChecker)
|
|
302
|
-
).rejects.toThrow(/Already connected/);
|
|
303
|
-
});
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
describe('disconnect', () => {
|
|
307
|
-
it('removes the chain and cleans up', async () => {
|
|
308
|
-
const provider = new ScProvider(mockSc, '');
|
|
309
|
-
|
|
310
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
311
|
-
const chain = mockSc.latestChain();
|
|
312
|
-
|
|
313
|
-
await provider.disconnect();
|
|
314
|
-
|
|
315
|
-
expect(chain._isTerminated()).toBe(true);
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
// eslint-disable-next-line jest/expect-expect
|
|
319
|
-
it('does not throw when disconnecting on an already disconnected Provider', async () => {
|
|
320
|
-
const provider = new ScProvider(mockSc, '');
|
|
321
|
-
|
|
322
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
323
|
-
await provider.disconnect();
|
|
324
|
-
await provider.disconnect();
|
|
325
|
-
});
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
describe('send', () => {
|
|
329
|
-
it('throws when trying to send a request while the Provider is not connected', async () => {
|
|
330
|
-
const provider = new ScProvider(mockSc, '');
|
|
331
|
-
|
|
332
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
333
|
-
|
|
334
|
-
await expect(provider.send('', [])).rejects.toThrow();
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
it('receives responses to its requests', async () => {
|
|
338
|
-
const provider = new ScProvider(mockSc, '');
|
|
339
|
-
|
|
340
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
341
|
-
const chain = mockSc.latestChain();
|
|
342
|
-
|
|
343
|
-
setChainSyncyingStatus(false);
|
|
344
|
-
|
|
345
|
-
const responsePromise = provider.send<unknown>('getData', ['foo']);
|
|
346
|
-
|
|
347
|
-
await wait(0);
|
|
348
|
-
expect(chain._getLatestRequest()).toEqual(
|
|
349
|
-
'{"id":1,"jsonrpc":"2.0","method":"getData","params":["foo"]}'
|
|
350
|
-
);
|
|
351
|
-
|
|
352
|
-
const result = { foo: 'foo' };
|
|
353
|
-
|
|
354
|
-
chain._triggerCallback({
|
|
355
|
-
id: 1,
|
|
356
|
-
jsonrpc: '2.0',
|
|
357
|
-
result
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
const response = await responsePromise;
|
|
361
|
-
|
|
362
|
-
expect(response).toEqual(result);
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
it("rejects when the response can't be deserialized", async () => {
|
|
366
|
-
const provider = new ScProvider(mockSc, '');
|
|
367
|
-
|
|
368
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
369
|
-
const chain = mockSc.latestChain();
|
|
370
|
-
|
|
371
|
-
setChainSyncyingStatus(false);
|
|
372
|
-
|
|
373
|
-
setTimeout(() => {
|
|
374
|
-
chain._triggerCallback({
|
|
375
|
-
id: 1,
|
|
376
|
-
jsonrpc: '2.0'
|
|
377
|
-
});
|
|
378
|
-
}, 0);
|
|
379
|
-
|
|
380
|
-
await expect(provider.send('getData', ['foo'])).rejects.toThrow();
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
it('rejects when the smoldot chain has crashed', async () => {
|
|
384
|
-
const provider = new ScProvider(mockSc, '');
|
|
385
|
-
|
|
386
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
387
|
-
const chain = mockSc.latestChain();
|
|
388
|
-
|
|
389
|
-
setChainSyncyingStatus(false);
|
|
390
|
-
await wait(0);
|
|
391
|
-
|
|
392
|
-
chain._setSendJsonRpcInterceptor(() => {
|
|
393
|
-
throw new Error('boom!');
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
await expect(
|
|
397
|
-
provider.send('getData', ['foo'])
|
|
398
|
-
).rejects.toThrow(/Disconnected/);
|
|
399
|
-
expect(provider.isConnected).toBe(false);
|
|
400
|
-
});
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
describe('subscribe', () => {
|
|
404
|
-
it('subscribes and recives messages until it unsubscribes', async () => {
|
|
405
|
-
const provider = new ScProvider(mockSc, '');
|
|
406
|
-
|
|
407
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
408
|
-
const chain = mockSc.latestChain();
|
|
409
|
-
|
|
410
|
-
setChainSyncyingStatus(false);
|
|
411
|
-
|
|
412
|
-
const unsubscribeToken = 'unsubscribeToken';
|
|
413
|
-
|
|
414
|
-
setTimeout(() => {
|
|
415
|
-
chain._triggerCallback({
|
|
416
|
-
id: 1,
|
|
417
|
-
jsonrpc: '2.0',
|
|
418
|
-
result: unsubscribeToken
|
|
419
|
-
});
|
|
420
|
-
}, 0);
|
|
421
|
-
|
|
422
|
-
const cb = jest.fn();
|
|
423
|
-
const token = await provider.subscribe(
|
|
424
|
-
'foo',
|
|
425
|
-
'chain_subscribeNewHeads',
|
|
426
|
-
['baz'],
|
|
427
|
-
cb
|
|
428
|
-
);
|
|
429
|
-
|
|
430
|
-
expect(token).toBe(unsubscribeToken);
|
|
431
|
-
expect(cb).not.toHaveBeenCalled();
|
|
432
|
-
|
|
433
|
-
chain._triggerCallback({
|
|
434
|
-
jsonrpc: '2.0',
|
|
435
|
-
method: 'foo',
|
|
436
|
-
params: {
|
|
437
|
-
result: 1,
|
|
438
|
-
subscription: token
|
|
439
|
-
}
|
|
440
|
-
});
|
|
441
|
-
expect(cb).toHaveBeenCalledTimes(1);
|
|
442
|
-
expect(cb).toHaveBeenLastCalledWith(null, 1);
|
|
443
|
-
|
|
444
|
-
chain._triggerCallback({
|
|
445
|
-
jsonrpc: '2.0',
|
|
446
|
-
method: 'foo',
|
|
447
|
-
params: {
|
|
448
|
-
result: 2,
|
|
449
|
-
subscription: token
|
|
450
|
-
}
|
|
451
|
-
});
|
|
452
|
-
expect(cb).toHaveBeenCalledTimes(2);
|
|
453
|
-
expect(cb).toHaveBeenLastCalledWith(null, 2);
|
|
454
|
-
|
|
455
|
-
provider
|
|
456
|
-
.unsubscribe('foo', 'chain_unsubscribeNewHeads', unsubscribeToken)
|
|
457
|
-
.catch(console.error);
|
|
458
|
-
|
|
459
|
-
chain._triggerCallback({
|
|
460
|
-
jsonrpc: '2.0',
|
|
461
|
-
method: 'foo',
|
|
462
|
-
params: {
|
|
463
|
-
result: 3,
|
|
464
|
-
subscription: token
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
expect(cb).toHaveBeenCalledTimes(2);
|
|
468
|
-
expect(cb).toHaveBeenLastCalledWith(null, 2);
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
it('ignores subscription messages that were received before the subscription token', async () => {
|
|
472
|
-
const provider = new ScProvider(mockSc, '');
|
|
473
|
-
|
|
474
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
475
|
-
const chain = mockSc.latestChain();
|
|
476
|
-
|
|
477
|
-
setChainSyncyingStatus(false);
|
|
478
|
-
|
|
479
|
-
const unsubscribeToken = 'unsubscribeToken';
|
|
480
|
-
|
|
481
|
-
chain._triggerCallback({
|
|
482
|
-
jsonrpc: '2.0',
|
|
483
|
-
method: 'foo',
|
|
484
|
-
params: {
|
|
485
|
-
result: 1,
|
|
486
|
-
subscription: unsubscribeToken
|
|
487
|
-
}
|
|
488
|
-
});
|
|
489
|
-
setTimeout(() => {
|
|
490
|
-
chain._triggerCallback({
|
|
491
|
-
id: 1,
|
|
492
|
-
jsonrpc: '2.0',
|
|
493
|
-
result: unsubscribeToken
|
|
494
|
-
});
|
|
495
|
-
}, 0);
|
|
496
|
-
|
|
497
|
-
const cb = jest.fn();
|
|
498
|
-
const token = await provider.subscribe(
|
|
499
|
-
'foo',
|
|
500
|
-
'chain_subscribeNewHeads',
|
|
501
|
-
['baz'],
|
|
502
|
-
cb
|
|
503
|
-
);
|
|
504
|
-
|
|
505
|
-
expect(token).toBe(unsubscribeToken);
|
|
506
|
-
expect(cb).not.toHaveBeenCalled();
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
it('emits the error when the message has an error', async () => {
|
|
510
|
-
const provider = new ScProvider(mockSc, '');
|
|
511
|
-
|
|
512
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
513
|
-
const chain = mockSc.latestChain();
|
|
514
|
-
|
|
515
|
-
setChainSyncyingStatus(false);
|
|
516
|
-
await wait(0);
|
|
517
|
-
|
|
518
|
-
const unsubscribeToken = 'unsubscribeToken';
|
|
519
|
-
|
|
520
|
-
setTimeout(() => {
|
|
521
|
-
chain._triggerCallback({
|
|
522
|
-
id: 1,
|
|
523
|
-
jsonrpc: '2.0',
|
|
524
|
-
result: unsubscribeToken
|
|
525
|
-
});
|
|
526
|
-
}, 0);
|
|
527
|
-
|
|
528
|
-
const cb = jest.fn();
|
|
529
|
-
const token = await provider.subscribe(
|
|
530
|
-
'foo',
|
|
531
|
-
'chain_subscribeNewHeads',
|
|
532
|
-
['baz'],
|
|
533
|
-
cb
|
|
534
|
-
);
|
|
535
|
-
|
|
536
|
-
chain._triggerCallback({
|
|
537
|
-
jsonrpc: '2.0',
|
|
538
|
-
method: 'foo',
|
|
539
|
-
params: {
|
|
540
|
-
error: 'boom',
|
|
541
|
-
subscription: unsubscribeToken
|
|
542
|
-
}
|
|
543
|
-
});
|
|
544
|
-
|
|
545
|
-
expect(token).toBe(unsubscribeToken);
|
|
546
|
-
expect(cb).toHaveBeenCalledTimes(1);
|
|
547
|
-
expect(cb).toHaveBeenLastCalledWith(expect.any(Error), undefined);
|
|
548
|
-
});
|
|
549
|
-
|
|
550
|
-
it('errors when subscribing to an unsupported method', async () => {
|
|
551
|
-
const provider = new ScProvider(mockSc, '');
|
|
552
|
-
|
|
553
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
554
|
-
|
|
555
|
-
setChainSyncyingStatus(false);
|
|
556
|
-
|
|
557
|
-
await wait(0);
|
|
558
|
-
await expect(
|
|
559
|
-
provider.subscribe('foo', 'bar', ['baz'], () => undefined)
|
|
560
|
-
).rejects.toThrow(/Unsupported subscribe method: bar/);
|
|
561
|
-
});
|
|
562
|
-
});
|
|
563
|
-
|
|
564
|
-
describe('unsubscribe', () => {
|
|
565
|
-
it('rejects when trying to unsubscribe from un unexisting subscription', async () => {
|
|
566
|
-
const provider = new ScProvider(mockSc, '');
|
|
567
|
-
|
|
568
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
569
|
-
|
|
570
|
-
setChainSyncyingStatus(false);
|
|
571
|
-
|
|
572
|
-
await expect(
|
|
573
|
-
provider.unsubscribe('', '', '')
|
|
574
|
-
).rejects.toThrow(/Unable to find active subscription/);
|
|
575
|
-
});
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
it('cleans up the stale subscriptions once it reconnects', async () => {
|
|
579
|
-
const provider = new ScProvider(mockSc, '');
|
|
580
|
-
|
|
581
|
-
await provider.connect(undefined, mockedHealthChecker.healthChecker);
|
|
582
|
-
const chain = mockSc.latestChain();
|
|
583
|
-
|
|
584
|
-
// setting the syncing status of the chain to fals so that the Provider
|
|
585
|
-
// gets `connected`
|
|
586
|
-
setChainSyncyingStatus(false);
|
|
587
|
-
|
|
588
|
-
// while connected we create a subscription
|
|
589
|
-
const unsubscribeToken = 'unsubscribeToken';
|
|
590
|
-
|
|
591
|
-
setTimeout(() => {
|
|
592
|
-
chain._triggerCallback({
|
|
593
|
-
id: 1,
|
|
594
|
-
jsonrpc: '2.0',
|
|
595
|
-
result: unsubscribeToken
|
|
596
|
-
});
|
|
597
|
-
}, 0);
|
|
598
|
-
|
|
599
|
-
const cb = jest.fn();
|
|
600
|
-
const token = await provider.subscribe(
|
|
601
|
-
'foo',
|
|
602
|
-
'chain_subscribeNewHeads',
|
|
603
|
-
['baz'],
|
|
604
|
-
cb
|
|
605
|
-
);
|
|
606
|
-
|
|
607
|
-
// setting the syncing status of the chain to fals so that the Provider
|
|
608
|
-
// gets `disconnected`
|
|
609
|
-
setChainSyncyingStatus(true);
|
|
610
|
-
|
|
611
|
-
// let's wait some time in order to ensure that the stale unsubscription
|
|
612
|
-
// messages are not sent until the chain syncing status changes back to false
|
|
613
|
-
await wait(200);
|
|
614
|
-
|
|
615
|
-
// before we let the healthChecker know that the chain is no longer syncing,
|
|
616
|
-
// let's make sure that the chain has received the correct request, and
|
|
617
|
-
// most importantly that it has not received a request for unsubscribing
|
|
618
|
-
// from the stale subscription, since that request should happen once the
|
|
619
|
-
// chain is no longer syncing
|
|
620
|
-
expect(chain._recevedRequests()).toEqual([
|
|
621
|
-
'{"id":1,"jsonrpc":"2.0","method":"chain_subscribeNewHeads","params":["baz"]}'
|
|
622
|
-
]);
|
|
623
|
-
|
|
624
|
-
// lets change the sync status back to false
|
|
625
|
-
setChainSyncyingStatus(false);
|
|
626
|
-
|
|
627
|
-
// let's wait one tick to ensure that the microtasks got processed
|
|
628
|
-
await wait(0);
|
|
629
|
-
|
|
630
|
-
// let's make sure that we have now sent the request for killing the
|
|
631
|
-
// stale subscription
|
|
632
|
-
expect(chain._recevedRequests()).toEqual([
|
|
633
|
-
'{"id":1,"jsonrpc":"2.0","method":"chain_subscribeNewHeads","params":["baz"]}',
|
|
634
|
-
`{"id":2,"jsonrpc":"2.0","method":"chain_unsubscribeNewHeads","params":["${token}"]}`,
|
|
635
|
-
'{"id":3,"jsonrpc":"2.0","method":"chain_subscribeNewHeads","params":["baz"]}'
|
|
636
|
-
]);
|
|
637
|
-
});
|
|
638
|
-
});
|