@polkadot-api/ws-provider 0.5.0 → 0.6.1

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 (44) hide show
  1. package/dist/index/esm/default-provider.mjs +153 -0
  2. package/dist/index/esm/default-provider.mjs.map +1 -0
  3. package/dist/index/esm/follow-enhancer.mjs +90 -0
  4. package/dist/index/esm/follow-enhancer.mjs.map +1 -0
  5. package/dist/index/esm/index.mjs +3 -0
  6. package/dist/index/esm/index.mjs.map +1 -0
  7. package/dist/{node/esm/types.mjs → index/esm/types-common.mjs} +1 -1
  8. package/dist/index/esm/types-common.mjs.map +1 -0
  9. package/dist/index/index.d.ts +47 -0
  10. package/dist/index/index.js +250 -0
  11. package/dist/index/index.js.map +1 -0
  12. package/dist/node/esm/default-provider.mjs +153 -0
  13. package/dist/node/esm/default-provider.mjs.map +1 -0
  14. package/dist/node/esm/follow-enhancer.mjs +8 -0
  15. package/dist/node/esm/follow-enhancer.mjs.map +1 -1
  16. package/dist/node/esm/legacy-provider.mjs +42 -0
  17. package/dist/node/esm/legacy-provider.mjs.map +1 -0
  18. package/dist/node/esm/node.mjs +3 -3
  19. package/dist/node/esm/node.mjs.map +1 -1
  20. package/dist/{web/esm/types.mjs → node/esm/types-common.mjs} +1 -1
  21. package/dist/node/esm/types-common.mjs.map +1 -0
  22. package/dist/node/node.d.ts +5 -0
  23. package/dist/node/node.js +163 -126
  24. package/dist/node/node.js.map +1 -1
  25. package/dist/web/esm/default-provider.mjs +153 -0
  26. package/dist/web/esm/default-provider.mjs.map +1 -0
  27. package/dist/web/esm/follow-enhancer.mjs +8 -0
  28. package/dist/web/esm/follow-enhancer.mjs.map +1 -1
  29. package/dist/web/esm/legacy-provider.mjs +42 -0
  30. package/dist/web/esm/legacy-provider.mjs.map +1 -0
  31. package/dist/web/esm/types-common.mjs +10 -0
  32. package/dist/web/esm/types-common.mjs.map +1 -0
  33. package/dist/web/esm/web.mjs +3 -3
  34. package/dist/web/esm/web.mjs.map +1 -1
  35. package/dist/web/web.d.ts +5 -0
  36. package/dist/web/web.js +163 -126
  37. package/dist/web/web.js.map +1 -1
  38. package/package.json +17 -6
  39. package/dist/node/esm/types.mjs.map +0 -1
  40. package/dist/node/esm/ws-provider.mjs +0 -162
  41. package/dist/node/esm/ws-provider.mjs.map +0 -1
  42. package/dist/web/esm/types.mjs.map +0 -1
  43. package/dist/web/esm/ws-provider.mjs +0 -162
  44. package/dist/web/esm/ws-provider.mjs.map +0 -1
@@ -0,0 +1,153 @@
1
+ import { getSyncProvider } from '@polkadot-api/json-rpc-provider-proxy';
2
+ import { WsEvent } from './types-common.mjs';
3
+ import { followEnhancer } from './follow-enhancer.mjs';
4
+
5
+ const timeoutError = {
6
+ type: WsEvent.ERROR,
7
+ event: { type: "timeout" }
8
+ };
9
+ const noop = () => {
10
+ };
11
+ const defaultConfig = {
12
+ onStatusChanged: noop,
13
+ innerEnhancer: (x) => x,
14
+ timeout: 5e3
15
+ };
16
+ const mapEndpoints = (endpoints) => endpoints.map((x) => typeof x === "string" ? [x] : [x.uri, x.protocol]);
17
+ const getWsProvider = (endpoints, config) => {
18
+ const { onStatusChanged, innerEnhancer, timeout } = {
19
+ ...defaultConfig,
20
+ ...config
21
+ };
22
+ const actualEndpoints = mapEndpoints(
23
+ Array.isArray(endpoints) ? endpoints : [endpoints]
24
+ );
25
+ const WebsocketClass = config?.websocketClass ?? globalThis.WebSocket;
26
+ if (!WebsocketClass) throw new Error("Missing WebSocket class");
27
+ let idx = 0;
28
+ let status;
29
+ let switchTo = null;
30
+ let disconnect = noop;
31
+ let outerCleanup = noop;
32
+ const result = followEnhancer(
33
+ getSyncProvider(async () => {
34
+ const [uri, protocols] = switchTo || actualEndpoints[idx++ % endpoints.length];
35
+ switchTo = null;
36
+ const socket = new WebsocketClass(uri, protocols);
37
+ const forceSocketClose = () => {
38
+ try {
39
+ socket.addEventListener("error", noop, { once: true });
40
+ socket.close();
41
+ } catch {
42
+ }
43
+ };
44
+ onStatusChanged(
45
+ status = {
46
+ type: WsEvent.CONNECTING,
47
+ uri,
48
+ protocols
49
+ }
50
+ );
51
+ await new Promise((resolve, reject) => {
52
+ const onOpen = () => {
53
+ initialCleanup();
54
+ resolve();
55
+ };
56
+ const onError = (e) => {
57
+ initialCleanup();
58
+ if (e == null) forceSocketClose();
59
+ console.error(
60
+ `Unable to connect to ${uri}${protocols ? ", protocols: " + protocols : ""}`
61
+ );
62
+ onStatusChanged(
63
+ status = {
64
+ type: e ? WsEvent.ERROR : WsEvent.CLOSE,
65
+ event: e
66
+ }
67
+ );
68
+ setTimeout(reject, e ? 300 : 0, e);
69
+ };
70
+ const timeoutToken = timeout !== Infinity ? setTimeout(() => {
71
+ initialCleanup();
72
+ forceSocketClose();
73
+ onStatusChanged(status = timeoutError);
74
+ reject(timeoutError.event);
75
+ }, timeout) : void 0;
76
+ const initialCleanup = () => {
77
+ clearTimeout(timeoutToken);
78
+ socket.removeEventListener("error", onError);
79
+ socket.removeEventListener("open", onOpen);
80
+ };
81
+ socket.addEventListener("open", onOpen);
82
+ socket.addEventListener("error", onError);
83
+ disconnect = () => {
84
+ onError(null);
85
+ };
86
+ });
87
+ onStatusChanged(
88
+ status = {
89
+ type: WsEvent.CONNECTED,
90
+ uri,
91
+ protocols
92
+ }
93
+ );
94
+ let _onInnerMessage;
95
+ const inner = innerEnhancer((onInnerMessage) => {
96
+ _onInnerMessage = onInnerMessage;
97
+ return {
98
+ send: (m) => {
99
+ socket.send(m);
100
+ },
101
+ disconnect: () => {
102
+ disconnect();
103
+ }
104
+ };
105
+ });
106
+ return (onMessage, onHalt) => {
107
+ const connection = inner(onMessage);
108
+ const _onMessage = (e) => {
109
+ if (typeof e.data === "string") _onInnerMessage(e.data);
110
+ };
111
+ const innerHalt = (reason) => (e) => {
112
+ console.warn(`WS halt (${reason})`);
113
+ onStatusChanged(
114
+ status = {
115
+ type: reason,
116
+ event: e
117
+ }
118
+ );
119
+ onHalt();
120
+ };
121
+ const onError = innerHalt(WsEvent.ERROR);
122
+ const onClose = innerHalt(WsEvent.CLOSE);
123
+ socket.addEventListener("message", _onMessage);
124
+ socket.addEventListener("error", onError);
125
+ socket.addEventListener("close", onClose);
126
+ disconnect = (withHalt) => {
127
+ outerCleanup();
128
+ disconnect = noop;
129
+ socket.removeEventListener("message", _onMessage);
130
+ socket.removeEventListener("error", onError);
131
+ socket.removeEventListener("close", onClose);
132
+ forceSocketClose();
133
+ if (withHalt) onClose({});
134
+ };
135
+ return connection;
136
+ };
137
+ }),
138
+ () => {
139
+ switchFn();
140
+ }
141
+ );
142
+ outerCleanup = result.cleanup;
143
+ delete result.cleanup;
144
+ const switchFn = (...args) => {
145
+ if (status.type === WsEvent.CLOSE) return;
146
+ if (args.length) switchTo = args;
147
+ if (status.type !== WsEvent.ERROR) disconnect(true);
148
+ };
149
+ return Object.assign(result, { switch: switchFn, getStatus: () => status });
150
+ };
151
+
152
+ export { defaultConfig, getWsProvider, mapEndpoints, noop };
153
+ //# sourceMappingURL=default-provider.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-provider.mjs","sources":["../../../src/default-provider.ts"],"sourcesContent":["import { getSyncProvider } from \"@polkadot-api/json-rpc-provider-proxy\"\nimport { StatusChange, WsJsonRpcProvider, WsEvent } from \"./types-common\"\nimport { followEnhancer } from \"./follow-enhancer\"\nimport { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\nimport { WebSocketClass } from \"./types-new\"\n\nconst timeoutError: StatusChange = {\n type: WsEvent.ERROR,\n event: { type: \"timeout\" },\n}\n\nexport const noop = () => {}\n\nexport const defaultConfig: {\n onStatusChanged: (status: StatusChange) => void\n innerEnhancer: (input: JsonRpcProvider) => JsonRpcProvider\n timeout: number\n} = {\n onStatusChanged: noop,\n innerEnhancer: (x: JsonRpcProvider) => x,\n timeout: 5_000,\n}\n\nexport const mapEndpoints = (\n endpoints: Array<string | { uri: string; protocol: string | string[] }>,\n): Array<[string, string | string[]] | [string]> =>\n endpoints.map((x) => (typeof x === \"string\" ? [x] : [x.uri, x.protocol]))\n\nexport const getWsProvider = (\n endpoints:\n | string\n | Array<string | { uri: string; protocol: string | string[] }>,\n config?: Partial<{\n onStatusChanged: (status: StatusChange) => void\n innerEnhancer: (input: JsonRpcProvider) => JsonRpcProvider\n timeout: number\n websocketClass: WebSocketClass\n }>,\n): WsJsonRpcProvider => {\n const { onStatusChanged, innerEnhancer, timeout } = {\n ...defaultConfig,\n ...config,\n }\n const actualEndpoints = mapEndpoints(\n Array.isArray(endpoints) ? endpoints : [endpoints],\n )\n const WebsocketClass = config?.websocketClass ?? globalThis.WebSocket\n if (!WebsocketClass) throw new Error(\"Missing WebSocket class\")\n\n let idx = 0\n let status: StatusChange\n let switchTo: [string] | [string, string | string[]] | null = null\n let disconnect: (withHalt?: boolean) => void = noop\n\n let outerCleanup: () => void = noop\n const result = followEnhancer(\n getSyncProvider(async () => {\n const [uri, protocols] =\n switchTo || actualEndpoints[idx++ % endpoints.length]\n switchTo = null\n const socket = new WebsocketClass(uri, protocols)\n const forceSocketClose = () => {\n try {\n socket.addEventListener(\"error\", noop, { once: true })\n socket.close()\n } catch {}\n }\n onStatusChanged(\n (status = {\n type: WsEvent.CONNECTING,\n uri,\n protocols,\n }),\n )\n\n await new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n initialCleanup()\n resolve()\n }\n\n const onError = (e: Event | null) => {\n initialCleanup()\n if (e == null) forceSocketClose()\n console.error(\n `Unable to connect to ${uri}${\n protocols ? \", protocols: \" + protocols : \"\"\n }`,\n )\n onStatusChanged(\n (status = {\n type: e ? WsEvent.ERROR : WsEvent.CLOSE,\n event: e,\n }),\n )\n setTimeout(reject, e ? 300 : 0, e)\n }\n\n const timeoutToken =\n timeout !== Infinity\n ? setTimeout(() => {\n initialCleanup()\n forceSocketClose()\n onStatusChanged((status = timeoutError))\n reject(timeoutError.event)\n }, timeout)\n : undefined\n\n const initialCleanup = () => {\n clearTimeout(timeoutToken)\n socket.removeEventListener(\"error\", onError)\n socket.removeEventListener(\"open\", onOpen)\n }\n socket.addEventListener(\"open\", onOpen)\n socket.addEventListener(\"error\", onError)\n disconnect = () => {\n onError(null)\n }\n })\n\n onStatusChanged(\n (status = {\n type: WsEvent.CONNECTED,\n uri,\n protocols,\n }),\n )\n\n let _onInnerMessage: (msg: string) => void\n const inner = innerEnhancer((onInnerMessage) => {\n _onInnerMessage = onInnerMessage\n return {\n send: (m) => {\n socket.send(m)\n },\n disconnect: () => {\n disconnect()\n },\n }\n })\n\n return (onMessage, onHalt) => {\n const connection = inner(onMessage)\n const _onMessage = (e: MessageEvent) => {\n if (typeof e.data === \"string\") _onInnerMessage(e.data)\n }\n const innerHalt =\n (reason: WsEvent.CLOSE | WsEvent.ERROR) => (e: any) => {\n console.warn(`WS halt (${reason})`)\n onStatusChanged(\n (status = {\n type: reason,\n event: e,\n }),\n )\n onHalt()\n }\n const onError = innerHalt(WsEvent.ERROR)\n const onClose = innerHalt(WsEvent.CLOSE)\n\n socket.addEventListener(\"message\", _onMessage)\n socket.addEventListener(\"error\", onError)\n socket.addEventListener(\"close\", onClose)\n disconnect = (withHalt) => {\n outerCleanup()\n disconnect = noop\n socket.removeEventListener(\"message\", _onMessage)\n socket.removeEventListener(\"error\", onError)\n socket.removeEventListener(\"close\", onClose)\n forceSocketClose()\n if (withHalt) onClose({})\n }\n\n return connection\n }\n }),\n () => {\n switchFn()\n },\n )\n outerCleanup = result.cleanup\n delete (result as any).cleanup\n\n const switchFn: WsJsonRpcProvider[\"switch\"] = (...args) => {\n if (status.type === WsEvent.CLOSE) return\n if (args.length) switchTo = args as any\n if (status.type !== WsEvent.ERROR) disconnect(true)\n }\n\n return Object.assign(result, { switch: switchFn, getStatus: () => status })\n}\n"],"names":[],"mappings":"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"}
@@ -10,6 +10,10 @@ const followEnhancer = (base, forceDisconnect) => {
10
10
  let methodsRequestId;
11
11
  const result = (onMsg) => {
12
12
  const { send, disconnect } = base((fromProvider) => {
13
+ let nStops = {
14
+ latest: Date.now(),
15
+ count: 0
16
+ };
13
17
  const parsed = JSON.parse(fromProvider);
14
18
  if ("id" in parsed) {
15
19
  const { id, result: result2 } = parsed;
@@ -48,11 +52,15 @@ const followEnhancer = (base, forceDisconnect) => {
48
52
  } else {
49
53
  const { subscription, result: result2 } = parsed.params;
50
54
  if (result2?.event === "stop") {
55
+ const diff = Date.now() - nStops.latest;
56
+ nStops.latest += diff;
57
+ nStops.count = diff < 1e3 ? nStops.count + 1 : 1;
51
58
  if (onGoing.has(subscription)) onGoing.delete(subscription);
52
59
  else prematureStops.add(subscription);
53
60
  }
54
61
  }
55
62
  onMsg(fromProvider);
63
+ if (nStops.count > 2) forceDisconnect();
56
64
  });
57
65
  return {
58
66
  send(toProvider) {
@@ -1 +1 @@
1
- {"version":3,"file":"follow-enhancer.mjs","sources":["../../../src/follow-enhancer.ts"],"sourcesContent":["import { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\n\nconst methods: Record<string, \"follow\" | \"unfollow\"> = {}\n;[\"v1\", \"unstable\"].forEach((version) => {\n methods[`chainHead_${version}_follow`] = \"follow\"\n methods[`chainHead_${version}_unfollow`] = \"unfollow\"\n})\n\nexport const followEnhancer: (\n input: JsonRpcProvider,\n forceDisconnect: () => void,\n) => JsonRpcProvider & {\n cleanup: () => void\n} = (base, forceDisconnect) => {\n const prematureStops = new Set<string>()\n const preOpId = new Map<string, string>()\n const onGoing = new Set<string>()\n let methodsRequestId: string | undefined\n\n const result: JsonRpcProvider = (onMsg) => {\n const { send, disconnect } = base((fromProvider) => {\n const parsed = JSON.parse(fromProvider)\n // it's a response\n if (\"id\" in parsed) {\n const { id, result } = parsed\n if (id === methodsRequestId) {\n methodsRequestId = undefined\n if (\n result &&\n !(result.methods as string[]).some((x) => {\n const [group, , name] = x.split(\"_\")\n return group === \"chainHead\" && name === \"follow\"\n })\n ) {\n onMsg(fromProvider)\n forceDisconnect()\n return\n }\n }\n\n const msg = preOpId.get(id)\n if (msg) {\n preOpId.delete(id)\n if (prematureStops.has(result)) {\n prematureStops.delete(result)\n return\n }\n\n onGoing.add(result)\n const currentSize = onGoing.size + preOpId.size\n if (currentSize > 2)\n console.warn(\n `Too many chainHead follow subscriptions (${currentSize})`,\n )\n else if (parsed.error) {\n console.warn(`chainHead follow failed on the ${currentSize} sub`)\n forceDisconnect()\n preOpId.set(id, msg)\n send(msg)\n return\n }\n }\n } else {\n // it's a notifiaction\n const { subscription, result } = (parsed as any).params\n if (result?.event === \"stop\") {\n if (onGoing.has(subscription)) onGoing.delete(subscription)\n else prematureStops.add(subscription)\n }\n }\n onMsg(fromProvider)\n })\n\n return {\n send(toProvider) {\n const parsed = JSON.parse(toProvider)\n if (parsed.method === \"rpc_methods\") methodsRequestId = parsed.id\n\n const method = methods[parsed.method]\n if (method === \"follow\") {\n preOpId.set(parsed.id, toProvider)\n } else if (method === \"unfollow\") {\n onGoing.delete(parsed.params[0])\n }\n send(toProvider)\n },\n disconnect,\n }\n }\n\n return Object.assign(result, {\n cleanup: () => {\n prematureStops.clear()\n preOpId.clear()\n onGoing.clear()\n },\n })\n}\n"],"names":["result"],"mappings":"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"}
1
+ {"version":3,"file":"follow-enhancer.mjs","sources":["../../../src/follow-enhancer.ts"],"sourcesContent":["import { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\n\nconst methods: Record<string, \"follow\" | \"unfollow\"> = {}\n;[\"v1\", \"unstable\"].forEach((version) => {\n methods[`chainHead_${version}_follow`] = \"follow\"\n methods[`chainHead_${version}_unfollow`] = \"unfollow\"\n})\n\nexport const followEnhancer: (\n input: JsonRpcProvider,\n forceDisconnect: () => void,\n) => JsonRpcProvider & {\n cleanup: () => void\n} = (base, forceDisconnect) => {\n const prematureStops = new Set<string>()\n const preOpId = new Map<string, string>()\n const onGoing = new Set<string>()\n let methodsRequestId: string | undefined\n\n const result: JsonRpcProvider = (onMsg) => {\n const { send, disconnect } = base((fromProvider) => {\n let nStops: { latest: number; count: number } = {\n latest: Date.now(),\n count: 0,\n }\n const parsed = JSON.parse(fromProvider)\n // it's a response\n if (\"id\" in parsed) {\n const { id, result } = parsed\n if (id === methodsRequestId) {\n methodsRequestId = undefined\n if (\n result &&\n !(result.methods as string[]).some((x) => {\n const [group, , name] = x.split(\"_\")\n return group === \"chainHead\" && name === \"follow\"\n })\n ) {\n onMsg(fromProvider)\n forceDisconnect()\n return\n }\n }\n\n const msg = preOpId.get(id)\n if (msg) {\n preOpId.delete(id)\n if (prematureStops.has(result)) {\n prematureStops.delete(result)\n return\n }\n\n onGoing.add(result)\n const currentSize = onGoing.size + preOpId.size\n if (currentSize > 2)\n console.warn(\n `Too many chainHead follow subscriptions (${currentSize})`,\n )\n else if (parsed.error) {\n console.warn(`chainHead follow failed on the ${currentSize} sub`)\n forceDisconnect()\n preOpId.set(id, msg)\n send(msg)\n return\n }\n }\n } else {\n // it's a notifiaction\n const { subscription, result } = (parsed as any).params\n if (result?.event === \"stop\") {\n const diff = Date.now() - nStops.latest\n nStops.latest += diff\n nStops.count = diff < 1000 ? nStops.count + 1 : 1\n\n if (onGoing.has(subscription)) onGoing.delete(subscription)\n else prematureStops.add(subscription)\n }\n }\n\n onMsg(fromProvider)\n if (nStops.count > 2) forceDisconnect()\n })\n\n return {\n send(toProvider) {\n const parsed = JSON.parse(toProvider)\n if (parsed.method === \"rpc_methods\") methodsRequestId = parsed.id\n\n const method = methods[parsed.method]\n if (method === \"follow\") {\n preOpId.set(parsed.id, toProvider)\n } else if (method === \"unfollow\") {\n onGoing.delete(parsed.params[0])\n }\n send(toProvider)\n },\n disconnect,\n }\n }\n\n return Object.assign(result, {\n cleanup: () => {\n prematureStops.clear()\n preOpId.clear()\n onGoing.clear()\n },\n })\n}\n"],"names":["result"],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { mapEndpoints, noop, defaultConfig, getWsProvider } from './default-provider.mjs';
2
+
3
+ const getLegacyWsProvider = (websocketClass) => {
4
+ return (...args) => {
5
+ let endpoints = [];
6
+ let { timeout, innerEnhancer, onStatusChanged } = defaultConfig;
7
+ const [firstArg] = args;
8
+ if (args.length === 1 && typeof firstArg === "object" && !Array.isArray(firstArg)) {
9
+ endpoints = mapEndpoints(firstArg.endpoints);
10
+ onStatusChanged = firstArg.onStatusChanged ?? noop;
11
+ timeout = firstArg.timeout ?? timeout;
12
+ innerEnhancer = firstArg.innerEnhancer ?? ((x) => x);
13
+ } else {
14
+ if (typeof args[1] === "function")
15
+ onStatusChanged = args[1];
16
+ if (Array.isArray(firstArg)) endpoints = mapEndpoints(firstArg);
17
+ else {
18
+ endpoints = [[firstArg]];
19
+ if (args[1] && args[1] !== onStatusChanged)
20
+ endpoints[0][1] = args[1];
21
+ if (args[2]) onStatusChanged = args[2];
22
+ }
23
+ }
24
+ return getWsProvider(
25
+ endpoints.map(
26
+ (x) => x.length === 1 ? x[0] : {
27
+ uri: x[0],
28
+ protocol: x[1]
29
+ }
30
+ ),
31
+ {
32
+ websocketClass,
33
+ onStatusChanged,
34
+ timeout,
35
+ innerEnhancer
36
+ }
37
+ );
38
+ };
39
+ };
40
+
41
+ export { getLegacyWsProvider };
42
+ //# sourceMappingURL=legacy-provider.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy-provider.mjs","sources":["../../../src/legacy-provider.ts"],"sourcesContent":["import type { StatusChange, WsJsonRpcProvider } from \"./types-common\"\nimport type { GetWsProviderInput } from \"./types-legacy\"\nimport {\n getWsProvider,\n mapEndpoints,\n defaultConfig,\n noop,\n} from \"./default-provider\"\nimport { type WebSocketClass } from \"./types-new\"\n\nexport const getLegacyWsProvider = (\n websocketClass: WebSocketClass,\n): GetWsProviderInput => {\n return (...args): WsJsonRpcProvider => {\n let endpoints: Array<[string, string | string[]] | [string]> = []\n let { timeout, innerEnhancer, onStatusChanged } = defaultConfig\n\n const [firstArg] = args\n if (\n args.length === 1 &&\n typeof firstArg === \"object\" &&\n !Array.isArray(firstArg)\n ) {\n endpoints = mapEndpoints(firstArg.endpoints)\n onStatusChanged = firstArg.onStatusChanged ?? noop\n timeout = firstArg.timeout ?? timeout\n innerEnhancer = firstArg.innerEnhancer ?? ((x) => x)\n } else {\n if (typeof args[1] === \"function\")\n onStatusChanged = args[1] as (status: StatusChange) => void\n if (Array.isArray(firstArg)) endpoints = mapEndpoints(firstArg)\n else {\n endpoints = [[firstArg as string]]\n if (args[1] && args[1] !== onStatusChanged)\n endpoints[0][1] = args[1] as any\n if (args[2]) onStatusChanged = args[2] as any\n }\n }\n\n return getWsProvider(\n endpoints.map((x) =>\n x.length === 1\n ? x[0]\n : {\n uri: x[0],\n protocol: x[1],\n },\n ),\n {\n websocketClass,\n onStatusChanged,\n timeout,\n innerEnhancer,\n },\n )\n }\n}\n"],"names":[],"mappings":";;AAUO,MAAM,mBAAA,GAAsB,CACjC,cAAA,KACuB;AACvB,EAAA,OAAO,IAAI,IAAA,KAA4B;AACrC,IAAA,IAAI,YAA2D,EAAC;AAChE,IAAA,IAAI,EAAE,OAAA,EAAS,aAAA,EAAe,eAAA,EAAgB,GAAI,aAAA;AAElD,IAAA,MAAM,CAAC,QAAQ,CAAA,GAAI,IAAA;AACnB,IAAA,IACE,IAAA,CAAK,MAAA,KAAW,CAAA,IAChB,OAAO,QAAA,KAAa,YACpB,CAAC,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA,EACvB;AACA,MAAA,SAAA,GAAY,YAAA,CAAa,SAAS,SAAS,CAAA;AAC3C,MAAA,eAAA,GAAkB,SAAS,eAAA,IAAmB,IAAA;AAC9C,MAAA,OAAA,GAAU,SAAS,OAAA,IAAW,OAAA;AAC9B,MAAA,aAAA,GAAgB,QAAA,CAAS,aAAA,KAAkB,CAAC,CAAA,KAAM,CAAA,CAAA;AAAA,IACpD,CAAA,MAAO;AACL,MAAA,IAAI,OAAO,IAAA,CAAK,CAAC,CAAA,KAAM,UAAA;AACrB,QAAA,eAAA,GAAkB,KAAK,CAAC,CAAA;AAC1B,MAAA,IAAI,MAAM,OAAA,CAAQ,QAAQ,CAAA,EAAG,SAAA,GAAY,aAAa,QAAQ,CAAA;AAAA,WACzD;AACH,QAAA,SAAA,GAAY,CAAC,CAAC,QAAkB,CAAC,CAAA;AACjC,QAAA,IAAI,IAAA,CAAK,CAAC,CAAA,IAAK,IAAA,CAAK,CAAC,CAAA,KAAM,eAAA;AACzB,UAAA,SAAA,CAAU,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAK,CAAC,CAAA;AAC1B,QAAA,IAAI,IAAA,CAAK,CAAC,CAAA,EAAG,eAAA,GAAkB,KAAK,CAAC,CAAA;AAAA,MACvC;AAAA,IACF;AAEA,IAAA,OAAO,aAAA;AAAA,MACL,SAAA,CAAU,GAAA;AAAA,QAAI,CAAC,CAAA,KACb,CAAA,CAAE,WAAW,CAAA,GACT,CAAA,CAAE,CAAC,CAAA,GACH;AAAA,UACE,GAAA,EAAK,EAAE,CAAC,CAAA;AAAA,UACR,QAAA,EAAU,EAAE,CAAC;AAAA;AACf,OACN;AAAA,MACA;AAAA,QACE,cAAA;AAAA,QACA,eAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA;AACF,KACF;AAAA,EACF,CAAA;AACF;;;;"}
@@ -1,13 +1,13 @@
1
1
  import { WebSocket } from 'ws';
2
- import { getInternalWsProvider } from './ws-provider.mjs';
3
- export { WsEvent } from './types.mjs';
2
+ import { getLegacyWsProvider } from './legacy-provider.mjs';
3
+ export { WsEvent } from './types-common.mjs';
4
4
 
5
5
  class WS extends WebSocket {
6
6
  close() {
7
7
  this.terminate();
8
8
  }
9
9
  }
10
- const getWsProvider = getInternalWsProvider(
10
+ const getWsProvider = getLegacyWsProvider(
11
11
  WS
12
12
  );
13
13
 
@@ -1 +1 @@
1
- {"version":3,"file":"node.mjs","sources":["../../../src/node.ts"],"sourcesContent":["import { WebSocket } from \"ws\"\nimport { getInternalWsProvider } from \"./ws-provider\"\nexport type { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\n\nexport * from \"./types\"\n\nclass WS extends WebSocket {\n close() {\n this.terminate()\n }\n}\n\nexport const getWsProvider = getInternalWsProvider(\n WS as unknown as typeof globalThis.WebSocket,\n)\n"],"names":[],"mappings":";;;;AAMA,MAAM,WAAW,SAAA,CAAU;AAAA,EACzB,KAAA,GAAQ;AACN,IAAA,IAAA,CAAK,SAAA,EAAU;AAAA,EACjB;AACF;AAEO,MAAM,aAAA,GAAgB,qBAAA;AAAA,EAC3B;AACF;;;;"}
1
+ {"version":3,"file":"node.mjs","sources":["../../../src/node.ts"],"sourcesContent":["import { WebSocket } from \"ws\"\nimport { getLegacyWsProvider } from \"./legacy-provider\"\nexport type { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\n\nexport * from \"./types-common\"\nexport * from \"./types-legacy\"\n\nclass WS extends WebSocket {\n close() {\n this.terminate()\n }\n}\n\n/**\n * @deprecated This export will be removed in PAPI v2. Migrate as follows:\n * `import { getWsProvider } from \"polkadot-api/ws-provider\"\n */\nexport const getWsProvider = getLegacyWsProvider(\n WS as unknown as typeof globalThis.WebSocket,\n)\n"],"names":[],"mappings":";;;;AAOA,MAAM,WAAW,SAAA,CAAU;AAAA,EACzB,KAAA,GAAQ;AACN,IAAA,IAAA,CAAK,SAAA,EAAU;AAAA,EACjB;AACF;AAMO,MAAM,aAAA,GAAgB,mBAAA;AAAA,EAC3B;AACF;;;;"}
@@ -7,4 +7,4 @@ var WsEvent = /* @__PURE__ */ ((WsEvent2) => {
7
7
  })(WsEvent || {});
8
8
 
9
9
  export { WsEvent };
10
- //# sourceMappingURL=types.mjs.map
10
+ //# sourceMappingURL=types-common.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-common.mjs","sources":["../../../src/types-common.ts"],"sourcesContent":["import { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\n\nexport enum WsEvent {\n CONNECTING,\n CONNECTED,\n ERROR,\n CLOSE,\n}\n\nexport type WsConnecting = {\n type: WsEvent.CONNECTING\n uri: string\n protocols?: string | string[]\n}\nexport type WsConnected = {\n type: WsEvent.CONNECTED\n uri: string\n protocols?: string | string[]\n}\nexport type WsError = {\n type: WsEvent.ERROR\n event: any\n}\nexport type WsClose = {\n type: WsEvent.CLOSE\n event: any\n}\nexport type StatusChange = WsConnecting | WsConnected | WsError | WsClose\nexport type WsJsonRpcProvider = JsonRpcProvider & {\n switch: (uri?: string, protocol?: string[]) => void\n getStatus: () => StatusChange\n}\nexport { type JsonRpcProvider }\n"],"names":["WsEvent"],"mappings":"AAEO,IAAK,OAAA,qBAAAA,QAAAA,KAAL;AACL,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,YAAA,CAAA,GAAA,CAAA,CAAA,GAAA,YAAA;AACA,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,WAAA,CAAA,GAAA,CAAA,CAAA,GAAA,WAAA;AACA,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,OAAA,CAAA,GAAA,CAAA,CAAA,GAAA,OAAA;AACA,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,OAAA,CAAA,GAAA,CAAA,CAAA,GAAA,OAAA;AAJU,EAAA,OAAAA,QAAAA;AAAA,CAAA,EAAA,OAAA,IAAA,EAAA;;;;"}
@@ -30,6 +30,7 @@ type WsJsonRpcProvider = JsonRpcProvider & {
30
30
  switch: (uri?: string, protocol?: string[]) => void;
31
31
  getStatus: () => StatusChange;
32
32
  };
33
+
33
34
  interface WsProviderConfig {
34
35
  endpoints: Array<string | {
35
36
  uri: string;
@@ -49,6 +50,10 @@ interface GetWsProviderInput {
49
50
  (wsProviderConfig: WsProviderConfig): WsJsonRpcProvider;
50
51
  }
51
52
 
53
+ /**
54
+ * @deprecated This export will be removed in PAPI v2. Migrate as follows:
55
+ * `import { getWsProvider } from "polkadot-api/ws-provider"
56
+ */
52
57
  declare const getWsProvider: GetWsProviderInput;
53
58
 
54
59
  export { WsEvent, getWsProvider };
package/dist/node/node.js CHANGED
@@ -23,6 +23,10 @@ const followEnhancer = (base, forceDisconnect) => {
23
23
  let methodsRequestId;
24
24
  const result = (onMsg) => {
25
25
  const { send, disconnect } = base((fromProvider) => {
26
+ let nStops = {
27
+ latest: Date.now(),
28
+ count: 0
29
+ };
26
30
  const parsed = JSON.parse(fromProvider);
27
31
  if ("id" in parsed) {
28
32
  const { id, result: result2 } = parsed;
@@ -61,11 +65,15 @@ const followEnhancer = (base, forceDisconnect) => {
61
65
  } else {
62
66
  const { subscription, result: result2 } = parsed.params;
63
67
  if (result2?.event === "stop") {
68
+ const diff = Date.now() - nStops.latest;
69
+ nStops.latest += diff;
70
+ nStops.count = diff < 1e3 ? nStops.count + 1 : 1;
64
71
  if (onGoing.has(subscription)) onGoing.delete(subscription);
65
72
  else prematureStops.add(subscription);
66
73
  }
67
74
  }
68
75
  onMsg(fromProvider);
76
+ if (nStops.count > 2) forceDisconnect();
69
77
  });
70
78
  return {
71
79
  send(toProvider) {
@@ -97,13 +105,151 @@ const timeoutError = {
97
105
  };
98
106
  const noop = () => {
99
107
  };
108
+ const defaultConfig = {
109
+ onStatusChanged: noop,
110
+ innerEnhancer: (x) => x,
111
+ timeout: 5e3
112
+ };
100
113
  const mapEndpoints = (endpoints) => endpoints.map((x) => typeof x === "string" ? [x] : [x.uri, x.protocol]);
101
- const getInternalWsProvider = (WebsocketClass) => {
114
+ const getWsProvider$1 = (endpoints, config) => {
115
+ const { onStatusChanged, innerEnhancer, timeout } = {
116
+ ...defaultConfig,
117
+ ...config
118
+ };
119
+ const actualEndpoints = mapEndpoints(
120
+ Array.isArray(endpoints) ? endpoints : [endpoints]
121
+ );
122
+ const WebsocketClass = config?.websocketClass ?? globalThis.WebSocket;
123
+ if (!WebsocketClass) throw new Error("Missing WebSocket class");
124
+ let idx = 0;
125
+ let status;
126
+ let switchTo = null;
127
+ let disconnect = noop;
128
+ let outerCleanup = noop;
129
+ const result = followEnhancer(
130
+ jsonRpcProviderProxy.getSyncProvider(async () => {
131
+ const [uri, protocols] = switchTo || actualEndpoints[idx++ % endpoints.length];
132
+ switchTo = null;
133
+ const socket = new WebsocketClass(uri, protocols);
134
+ const forceSocketClose = () => {
135
+ try {
136
+ socket.addEventListener("error", noop, { once: true });
137
+ socket.close();
138
+ } catch {
139
+ }
140
+ };
141
+ onStatusChanged(
142
+ status = {
143
+ type: WsEvent.CONNECTING,
144
+ uri,
145
+ protocols
146
+ }
147
+ );
148
+ await new Promise((resolve, reject) => {
149
+ const onOpen = () => {
150
+ initialCleanup();
151
+ resolve();
152
+ };
153
+ const onError = (e) => {
154
+ initialCleanup();
155
+ if (e == null) forceSocketClose();
156
+ console.error(
157
+ `Unable to connect to ${uri}${protocols ? ", protocols: " + protocols : ""}`
158
+ );
159
+ onStatusChanged(
160
+ status = {
161
+ type: e ? WsEvent.ERROR : WsEvent.CLOSE,
162
+ event: e
163
+ }
164
+ );
165
+ setTimeout(reject, e ? 300 : 0, e);
166
+ };
167
+ const timeoutToken = timeout !== Infinity ? setTimeout(() => {
168
+ initialCleanup();
169
+ forceSocketClose();
170
+ onStatusChanged(status = timeoutError);
171
+ reject(timeoutError.event);
172
+ }, timeout) : void 0;
173
+ const initialCleanup = () => {
174
+ clearTimeout(timeoutToken);
175
+ socket.removeEventListener("error", onError);
176
+ socket.removeEventListener("open", onOpen);
177
+ };
178
+ socket.addEventListener("open", onOpen);
179
+ socket.addEventListener("error", onError);
180
+ disconnect = () => {
181
+ onError(null);
182
+ };
183
+ });
184
+ onStatusChanged(
185
+ status = {
186
+ type: WsEvent.CONNECTED,
187
+ uri,
188
+ protocols
189
+ }
190
+ );
191
+ let _onInnerMessage;
192
+ const inner = innerEnhancer((onInnerMessage) => {
193
+ _onInnerMessage = onInnerMessage;
194
+ return {
195
+ send: (m) => {
196
+ socket.send(m);
197
+ },
198
+ disconnect: () => {
199
+ disconnect();
200
+ }
201
+ };
202
+ });
203
+ return (onMessage, onHalt) => {
204
+ const connection = inner(onMessage);
205
+ const _onMessage = (e) => {
206
+ if (typeof e.data === "string") _onInnerMessage(e.data);
207
+ };
208
+ const innerHalt = (reason) => (e) => {
209
+ console.warn(`WS halt (${reason})`);
210
+ onStatusChanged(
211
+ status = {
212
+ type: reason,
213
+ event: e
214
+ }
215
+ );
216
+ onHalt();
217
+ };
218
+ const onError = innerHalt(WsEvent.ERROR);
219
+ const onClose = innerHalt(WsEvent.CLOSE);
220
+ socket.addEventListener("message", _onMessage);
221
+ socket.addEventListener("error", onError);
222
+ socket.addEventListener("close", onClose);
223
+ disconnect = (withHalt) => {
224
+ outerCleanup();
225
+ disconnect = noop;
226
+ socket.removeEventListener("message", _onMessage);
227
+ socket.removeEventListener("error", onError);
228
+ socket.removeEventListener("close", onClose);
229
+ forceSocketClose();
230
+ if (withHalt) onClose({});
231
+ };
232
+ return connection;
233
+ };
234
+ }),
235
+ () => {
236
+ switchFn();
237
+ }
238
+ );
239
+ outerCleanup = result.cleanup;
240
+ delete result.cleanup;
241
+ const switchFn = (...args) => {
242
+ if (status.type === WsEvent.CLOSE) return;
243
+ if (args.length) switchTo = args;
244
+ if (status.type !== WsEvent.ERROR) disconnect(true);
245
+ };
246
+ return Object.assign(result, { switch: switchFn, getStatus: () => status });
247
+ };
248
+
249
+ const getLegacyWsProvider = (websocketClass) => {
102
250
  return (...args) => {
103
251
  let endpoints = [];
104
- let onStatusChanged = noop;
105
- let timeout = 3500;
106
- let innerEnhancer = (x) => x;
252
+ let { timeout, innerEnhancer, onStatusChanged } = defaultConfig;
107
253
  const [firstArg] = args;
108
254
  if (args.length === 1 && typeof firstArg === "object" && !Array.isArray(firstArg)) {
109
255
  endpoints = mapEndpoints(firstArg.endpoints);
@@ -121,129 +267,20 @@ const getInternalWsProvider = (WebsocketClass) => {
121
267
  if (args[2]) onStatusChanged = args[2];
122
268
  }
123
269
  }
124
- let idx = 0;
125
- let status;
126
- let switchTo = null;
127
- let disconnect = noop;
128
- let outerCleanup = noop;
129
- const result = followEnhancer(
130
- jsonRpcProviderProxy.getSyncProvider(async () => {
131
- const [uri, protocols] = switchTo || endpoints[idx++ % endpoints.length];
132
- switchTo = null;
133
- const socket = new WebsocketClass(uri, protocols);
134
- const forceSocketClose = () => {
135
- try {
136
- socket.addEventListener("error", noop, { once: true });
137
- socket.close();
138
- } catch {
139
- }
140
- };
141
- onStatusChanged(
142
- status = {
143
- type: WsEvent.CONNECTING,
144
- uri,
145
- protocols
146
- }
147
- );
148
- await new Promise((resolve, reject) => {
149
- const onOpen = () => {
150
- initialCleanup();
151
- resolve();
152
- };
153
- const onError = (e) => {
154
- initialCleanup();
155
- if (e == null) forceSocketClose();
156
- console.error(
157
- `Unable to connect to ${uri}${protocols ? ", protocols: " + protocols : ""}`
158
- );
159
- onStatusChanged(
160
- status = {
161
- type: e ? WsEvent.ERROR : WsEvent.CLOSE,
162
- event: e
163
- }
164
- );
165
- setTimeout(reject, e ? 300 : 0, e);
166
- };
167
- const timeoutToken = timeout !== Infinity ? setTimeout(() => {
168
- initialCleanup();
169
- forceSocketClose();
170
- onStatusChanged(status = timeoutError);
171
- reject(timeoutError.event);
172
- }, timeout) : void 0;
173
- const initialCleanup = () => {
174
- clearTimeout(timeoutToken);
175
- socket.removeEventListener("error", onError);
176
- socket.removeEventListener("open", onOpen);
177
- };
178
- socket.addEventListener("open", onOpen);
179
- socket.addEventListener("error", onError);
180
- disconnect = () => {
181
- onError(null);
182
- };
183
- });
184
- onStatusChanged(
185
- status = {
186
- type: WsEvent.CONNECTED,
187
- uri,
188
- protocols
189
- }
190
- );
191
- let _onInnerMessage;
192
- const inner = innerEnhancer((onInnerMessage) => {
193
- _onInnerMessage = onInnerMessage;
194
- return {
195
- send: (m) => {
196
- socket.send(m);
197
- },
198
- disconnect: () => {
199
- disconnect();
200
- }
201
- };
202
- });
203
- return (onMessage, onHalt) => {
204
- const connection = inner(onMessage);
205
- const _onMessage = (e) => {
206
- if (typeof e.data === "string") _onInnerMessage(e.data);
207
- };
208
- const innerHalt = (reason) => (e) => {
209
- console.warn(`WS halt (${reason})`);
210
- onStatusChanged(
211
- status = {
212
- type: reason,
213
- event: e
214
- }
215
- );
216
- onHalt();
217
- };
218
- const onError = innerHalt(WsEvent.ERROR);
219
- const onClose = innerHalt(WsEvent.CLOSE);
220
- socket.addEventListener("message", _onMessage);
221
- socket.addEventListener("error", onError);
222
- socket.addEventListener("close", onClose);
223
- disconnect = (withHalt) => {
224
- outerCleanup();
225
- disconnect = noop;
226
- socket.removeEventListener("message", _onMessage);
227
- socket.removeEventListener("error", onError);
228
- socket.removeEventListener("close", onClose);
229
- forceSocketClose();
230
- if (withHalt) onClose({});
231
- };
232
- return connection;
233
- };
234
- }),
235
- () => {
236
- switchFn();
270
+ return getWsProvider$1(
271
+ endpoints.map(
272
+ (x) => x.length === 1 ? x[0] : {
273
+ uri: x[0],
274
+ protocol: x[1]
275
+ }
276
+ ),
277
+ {
278
+ websocketClass,
279
+ onStatusChanged,
280
+ timeout,
281
+ innerEnhancer
237
282
  }
238
283
  );
239
- outerCleanup = result.cleanup;
240
- delete result.cleanup;
241
- const switchFn = (...args2) => {
242
- if (status.type === WsEvent.CLOSE) return;
243
- if (args2.length) switchTo = args2;
244
- if (status.type !== WsEvent.ERROR) disconnect(true);
245
- };
246
- return Object.assign(result, { switch: switchFn, getStatus: () => status });
247
284
  };
248
285
  };
249
286
 
@@ -252,7 +289,7 @@ class WS extends ws.WebSocket {
252
289
  this.terminate();
253
290
  }
254
291
  }
255
- const getWsProvider = getInternalWsProvider(
292
+ const getWsProvider = getLegacyWsProvider(
256
293
  WS
257
294
  );
258
295