@polkadot-api/ws-provider 0.3.3 → 0.3.5

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.
@@ -0,0 +1,66 @@
1
+ const methods = {};
2
+ ["v1", "unstable"].forEach((version) => {
3
+ methods[`chainHead_${version}_follow`] = "follow";
4
+ methods[`chainHead_${version}_unfollow`] = "unfollow";
5
+ });
6
+ const followEnhancer = (base, forceDisconnect) => {
7
+ const prematureStops = /* @__PURE__ */ new Set();
8
+ const preOpId = /* @__PURE__ */ new Set();
9
+ const onGoing = /* @__PURE__ */ new Set();
10
+ const result = (onMsg) => {
11
+ const { send, disconnect } = base((fromProvider) => {
12
+ const parsed = JSON.parse(fromProvider);
13
+ if ("id" in parsed) {
14
+ const { id, result: result2 } = parsed;
15
+ if (preOpId.has(id)) {
16
+ preOpId.delete(id);
17
+ if (prematureStops.has(result2)) {
18
+ prematureStops.delete(result2);
19
+ return;
20
+ }
21
+ onGoing.add(result2);
22
+ const currentSize = onGoing.size + preOpId.size;
23
+ if (currentSize > 2)
24
+ console.warn(
25
+ `Too many chainHead follow subscriptions (${currentSize})`
26
+ );
27
+ else if (parsed.error) {
28
+ console.warn(`chainHead follow failed on the ${currentSize} sub`);
29
+ Promise.resolve().then(forceDisconnect);
30
+ return;
31
+ }
32
+ }
33
+ } else {
34
+ const { subscription, result: result2 } = parsed.params;
35
+ if (result2?.event === "stop") {
36
+ if (onGoing.has(subscription)) onGoing.delete(subscription);
37
+ else prematureStops.add(subscription);
38
+ }
39
+ }
40
+ onMsg(fromProvider);
41
+ });
42
+ return {
43
+ send(toProvider) {
44
+ const parsed = JSON.parse(toProvider);
45
+ const method = methods[parsed.method];
46
+ if (method === "follow") {
47
+ preOpId.add(parsed.id);
48
+ } else if (method === "unfollow") {
49
+ onGoing.delete(parsed.params[0]);
50
+ }
51
+ send(toProvider);
52
+ },
53
+ disconnect
54
+ };
55
+ };
56
+ return Object.assign(result, {
57
+ cleanup: () => {
58
+ prematureStops.clear();
59
+ preOpId.clear();
60
+ onGoing.clear();
61
+ }
62
+ });
63
+ };
64
+
65
+ export { followEnhancer };
66
+ //# sourceMappingURL=follow-enhancer.mjs.map
@@ -0,0 +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 Set<string>()\n const onGoing = new Set<string>()\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 (preOpId.has(id)) {\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 Promise.resolve().then(forceDisconnect)\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 const method = methods[parsed.method]\n if (method === \"follow\") {\n preOpId.add(parsed.id)\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,5 +1,6 @@
1
1
  import { getSyncProvider } from '@polkadot-api/json-rpc-provider-proxy';
2
2
  import { WsEvent } from './types.mjs';
3
+ import { followEnhancer } from './follow-enhancer.mjs';
3
4
 
4
5
  const timeoutError = {
5
6
  type: WsEvent.ERROR,
@@ -33,108 +34,117 @@ const getInternalWsProvider = (WebsocketClass) => {
33
34
  let status;
34
35
  let switchTo = null;
35
36
  let disconnect = noop;
36
- const result = getSyncProvider(async () => {
37
- const [uri, protocols] = switchTo || endpoints[idx++ % endpoints.length];
38
- switchTo = null;
39
- const socket = new WebsocketClass(uri, protocols);
40
- const forceSocketClose = () => {
41
- try {
42
- socket.close();
43
- } catch {
44
- }
45
- };
46
- onStatusChanged(
47
- status = {
48
- type: WsEvent.CONNECTING,
49
- uri,
50
- protocols
51
- }
52
- );
53
- await new Promise((resolve, reject) => {
54
- const onOpen = () => {
55
- initialCleanup();
56
- resolve();
37
+ let outerCleanup = noop;
38
+ const result = followEnhancer(
39
+ getSyncProvider(async () => {
40
+ const [uri, protocols] = switchTo || endpoints[idx++ % endpoints.length];
41
+ switchTo = null;
42
+ const socket = new WebsocketClass(uri, protocols);
43
+ const forceSocketClose = () => {
44
+ try {
45
+ socket.addEventListener("error", noop, { once: true });
46
+ socket.close();
47
+ } catch {
48
+ }
57
49
  };
58
- const onError = (e) => {
59
- initialCleanup();
60
- if (e == null) forceSocketClose();
61
- console.error(
62
- `Unable to connect to ${uri}${protocols ? ", protocols: " + protocols : ""}`
63
- );
64
- onStatusChanged(
65
- status = {
66
- type: e ? WsEvent.ERROR : WsEvent.CLOSE,
67
- event: e
68
- }
69
- );
70
- setTimeout(reject, e ? 300 : 0, e);
50
+ onStatusChanged(
51
+ status = {
52
+ type: WsEvent.CONNECTING,
53
+ uri,
54
+ protocols
55
+ }
56
+ );
57
+ await new Promise((resolve, reject) => {
58
+ const onOpen = () => {
59
+ initialCleanup();
60
+ resolve();
61
+ };
62
+ const onError = (e) => {
63
+ initialCleanup();
64
+ if (e == null) forceSocketClose();
65
+ console.error(
66
+ `Unable to connect to ${uri}${protocols ? ", protocols: " + protocols : ""}`
67
+ );
68
+ onStatusChanged(
69
+ status = {
70
+ type: e ? WsEvent.ERROR : WsEvent.CLOSE,
71
+ event: e
72
+ }
73
+ );
74
+ setTimeout(reject, e ? 300 : 0, e);
75
+ };
76
+ const timeoutToken = timeout !== Infinity ? setTimeout(() => {
77
+ initialCleanup();
78
+ forceSocketClose();
79
+ onStatusChanged(status = timeoutError);
80
+ reject(timeoutError.event);
81
+ }, timeout) : void 0;
82
+ const initialCleanup = () => {
83
+ clearTimeout(timeoutToken);
84
+ socket.removeEventListener("error", onError);
85
+ socket.removeEventListener("open", onOpen);
86
+ };
87
+ socket.addEventListener("open", onOpen);
88
+ socket.addEventListener("error", onError);
89
+ disconnect = () => {
90
+ onError(null);
91
+ };
92
+ });
93
+ onStatusChanged(
94
+ status = {
95
+ type: WsEvent.CONNECTED,
96
+ uri,
97
+ protocols
98
+ }
99
+ );
100
+ return (onMessage, onHalt) => {
101
+ const _onMessage = (e) => {
102
+ if (typeof e.data === "string") onMessage(e.data);
103
+ };
104
+ const innerHalt = (reason) => (e) => {
105
+ console.warn(`WS halt (${reason})`);
106
+ onStatusChanged(
107
+ status = {
108
+ type: reason,
109
+ event: e
110
+ }
111
+ );
112
+ onHalt();
113
+ };
114
+ const onError = innerHalt(WsEvent.ERROR);
115
+ const onClose = innerHalt(WsEvent.CLOSE);
116
+ socket.addEventListener("message", _onMessage);
117
+ socket.addEventListener("error", onError);
118
+ socket.addEventListener("close", onClose);
119
+ disconnect = (withHalt) => {
120
+ outerCleanup();
121
+ disconnect = noop;
122
+ socket.removeEventListener("message", _onMessage);
123
+ socket.removeEventListener("error", onError);
124
+ socket.removeEventListener("close", onClose);
125
+ forceSocketClose();
126
+ if (withHalt) onClose({});
127
+ };
128
+ return {
129
+ send: (msg) => {
130
+ socket.send(msg);
131
+ },
132
+ disconnect
133
+ };
71
134
  };
72
- const timeoutToken = timeout !== Infinity ? setTimeout(() => {
73
- initialCleanup();
74
- forceSocketClose();
75
- onStatusChanged(status = timeoutError);
76
- reject(timeoutError.event);
77
- }, timeout) : void 0;
78
- const initialCleanup = () => {
79
- clearTimeout(timeoutToken);
80
- socket.removeEventListener("error", onError);
81
- socket.removeEventListener("open", onOpen);
82
- };
83
- socket.addEventListener("open", onOpen);
84
- socket.addEventListener("error", onError);
85
- disconnect = () => {
86
- onError(null);
87
- };
88
- });
89
- onStatusChanged(
90
- status = {
91
- type: WsEvent.CONNECTED,
92
- uri,
93
- protocols
94
- }
95
- );
96
- return (onMessage, onHalt) => {
97
- const _onMessage = (e) => {
98
- if (typeof e.data === "string") onMessage(e.data);
99
- };
100
- const innerHalt = (reason) => (e) => {
101
- console.warn(`WS halt (${reason})`);
102
- onStatusChanged(
103
- status = {
104
- type: reason,
105
- event: e
106
- }
107
- );
108
- onHalt();
109
- };
110
- const onError = innerHalt(WsEvent.ERROR);
111
- const onClose = innerHalt(WsEvent.CLOSE);
112
- socket.addEventListener("message", _onMessage);
113
- socket.addEventListener("error", onError);
114
- socket.addEventListener("close", onClose);
115
- disconnect = (withHalt) => {
116
- disconnect = noop;
117
- socket.removeEventListener("message", _onMessage);
118
- socket.removeEventListener("error", onError);
119
- socket.removeEventListener("close", onClose);
120
- forceSocketClose();
121
- if (withHalt) onClose({});
122
- };
123
- return {
124
- send: (msg) => {
125
- socket.send(msg);
126
- },
127
- disconnect
128
- };
129
- };
130
- });
131
- result.getStatus = () => status;
132
- result.switch = (...args2) => {
135
+ }),
136
+ () => {
137
+ switchFn();
138
+ }
139
+ );
140
+ outerCleanup = result.cleanup;
141
+ delete result.cleanup;
142
+ const switchFn = (...args2) => {
133
143
  if (status.type === WsEvent.CLOSE) return;
134
144
  if (args2.length) switchTo = args2;
135
145
  if (status.type !== WsEvent.ERROR) disconnect(true);
136
146
  };
137
- return result;
147
+ return Object.assign(result, { switch: switchFn, getStatus: () => status });
138
148
  };
139
149
  };
140
150
 
@@ -1 +1 @@
1
- {"version":3,"file":"ws-provider.mjs","sources":["../../../src/ws-provider.ts"],"sourcesContent":["import { getSyncProvider } from \"@polkadot-api/json-rpc-provider-proxy\"\nimport {\n GetWsProviderInput,\n StatusChange,\n WsJsonRpcProvider,\n WsEvent,\n WsProviderConfig,\n} from \"./types\"\n\nconst timeoutError: StatusChange = {\n type: WsEvent.ERROR,\n event: { type: \"timeout\" },\n}\n\nconst noop = () => {}\n\nconst mapEndpoints = (\n endpoints: WsProviderConfig[\"endpoints\"],\n): Array<[string, string | string[]] | [string]> =>\n endpoints.map((x) => (typeof x === \"string\" ? [x] : [x.uri, x.protocol]))\n\nexport const getInternalWsProvider = (\n WebsocketClass: typeof WebSocket,\n): GetWsProviderInput => {\n return (...args): WsJsonRpcProvider => {\n let endpoints: Array<[string, string | string[]] | [string]> = []\n let onStatusChanged: (status: StatusChange) => void = noop\n let timeout = 3_500\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 } 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 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 const result = getSyncProvider(async () => {\n const [uri, protocols] = switchTo || endpoints[idx++ % endpoints.length]\n switchTo = null\n const socket = new WebsocketClass(uri, protocols)\n const forceSocketClose = () => {\n try {\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 return (onMessage, onHalt) => {\n const _onMessage = (e: MessageEvent) => {\n if (typeof e.data === \"string\") onMessage(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 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 {\n send: (msg) => {\n socket.send(msg)\n },\n disconnect,\n }\n }\n }) as WsJsonRpcProvider\n\n result.getStatus = () => status\n result.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 return result\n }\n}\n"],"names":["args"],"mappings":"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"}
1
+ {"version":3,"file":"ws-provider.mjs","sources":["../../../src/ws-provider.ts"],"sourcesContent":["import { getSyncProvider } from \"@polkadot-api/json-rpc-provider-proxy\"\nimport {\n GetWsProviderInput,\n StatusChange,\n WsJsonRpcProvider,\n WsEvent,\n WsProviderConfig,\n} from \"./types\"\nimport { followEnhancer } from \"./follow-enhancer\"\n\nconst timeoutError: StatusChange = {\n type: WsEvent.ERROR,\n event: { type: \"timeout\" },\n}\n\nconst noop = () => {}\n\nconst mapEndpoints = (\n endpoints: WsProviderConfig[\"endpoints\"],\n): Array<[string, string | string[]] | [string]> =>\n endpoints.map((x) => (typeof x === \"string\" ? [x] : [x.uri, x.protocol]))\n\nexport const getInternalWsProvider = (\n WebsocketClass: typeof WebSocket,\n): GetWsProviderInput => {\n return (...args): WsJsonRpcProvider => {\n let endpoints: Array<[string, string | string[]] | [string]> = []\n let onStatusChanged: (status: StatusChange) => void = noop\n let timeout = 3_500\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 } 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 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] = switchTo || endpoints[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 return (onMessage, onHalt) => {\n const _onMessage = (e: MessageEvent) => {\n if (typeof e.data === \"string\") onMessage(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 {\n send: (msg) => {\n socket.send(msg)\n },\n disconnect,\n }\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}\n"],"names":["args"],"mappings":"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"}
package/dist/node/node.js CHANGED
@@ -11,6 +11,70 @@ var WsEvent = /* @__PURE__ */ ((WsEvent2) => {
11
11
  return WsEvent2;
12
12
  })(WsEvent || {});
13
13
 
14
+ const methods = {};
15
+ ["v1", "unstable"].forEach((version) => {
16
+ methods[`chainHead_${version}_follow`] = "follow";
17
+ methods[`chainHead_${version}_unfollow`] = "unfollow";
18
+ });
19
+ const followEnhancer = (base, forceDisconnect) => {
20
+ const prematureStops = /* @__PURE__ */ new Set();
21
+ const preOpId = /* @__PURE__ */ new Set();
22
+ const onGoing = /* @__PURE__ */ new Set();
23
+ const result = (onMsg) => {
24
+ const { send, disconnect } = base((fromProvider) => {
25
+ const parsed = JSON.parse(fromProvider);
26
+ if ("id" in parsed) {
27
+ const { id, result: result2 } = parsed;
28
+ if (preOpId.has(id)) {
29
+ preOpId.delete(id);
30
+ if (prematureStops.has(result2)) {
31
+ prematureStops.delete(result2);
32
+ return;
33
+ }
34
+ onGoing.add(result2);
35
+ const currentSize = onGoing.size + preOpId.size;
36
+ if (currentSize > 2)
37
+ console.warn(
38
+ `Too many chainHead follow subscriptions (${currentSize})`
39
+ );
40
+ else if (parsed.error) {
41
+ console.warn(`chainHead follow failed on the ${currentSize} sub`);
42
+ Promise.resolve().then(forceDisconnect);
43
+ return;
44
+ }
45
+ }
46
+ } else {
47
+ const { subscription, result: result2 } = parsed.params;
48
+ if (result2?.event === "stop") {
49
+ if (onGoing.has(subscription)) onGoing.delete(subscription);
50
+ else prematureStops.add(subscription);
51
+ }
52
+ }
53
+ onMsg(fromProvider);
54
+ });
55
+ return {
56
+ send(toProvider) {
57
+ const parsed = JSON.parse(toProvider);
58
+ const method = methods[parsed.method];
59
+ if (method === "follow") {
60
+ preOpId.add(parsed.id);
61
+ } else if (method === "unfollow") {
62
+ onGoing.delete(parsed.params[0]);
63
+ }
64
+ send(toProvider);
65
+ },
66
+ disconnect
67
+ };
68
+ };
69
+ return Object.assign(result, {
70
+ cleanup: () => {
71
+ prematureStops.clear();
72
+ preOpId.clear();
73
+ onGoing.clear();
74
+ }
75
+ });
76
+ };
77
+
14
78
  const timeoutError = {
15
79
  type: WsEvent.ERROR,
16
80
  event: { type: "timeout" }
@@ -43,108 +107,117 @@ const getInternalWsProvider = (WebsocketClass) => {
43
107
  let status;
44
108
  let switchTo = null;
45
109
  let disconnect = noop;
46
- const result = jsonRpcProviderProxy.getSyncProvider(async () => {
47
- const [uri, protocols] = switchTo || endpoints[idx++ % endpoints.length];
48
- switchTo = null;
49
- const socket = new WebsocketClass(uri, protocols);
50
- const forceSocketClose = () => {
51
- try {
52
- socket.close();
53
- } catch {
54
- }
55
- };
56
- onStatusChanged(
57
- status = {
58
- type: WsEvent.CONNECTING,
59
- uri,
60
- protocols
61
- }
62
- );
63
- await new Promise((resolve, reject) => {
64
- const onOpen = () => {
65
- initialCleanup();
66
- resolve();
67
- };
68
- const onError = (e) => {
69
- initialCleanup();
70
- if (e == null) forceSocketClose();
71
- console.error(
72
- `Unable to connect to ${uri}${protocols ? ", protocols: " + protocols : ""}`
73
- );
74
- onStatusChanged(
75
- status = {
76
- type: e ? WsEvent.ERROR : WsEvent.CLOSE,
77
- event: e
78
- }
79
- );
80
- setTimeout(reject, e ? 300 : 0, e);
81
- };
82
- const timeoutToken = timeout !== Infinity ? setTimeout(() => {
83
- initialCleanup();
84
- forceSocketClose();
85
- onStatusChanged(status = timeoutError);
86
- reject(timeoutError.event);
87
- }, timeout) : void 0;
88
- const initialCleanup = () => {
89
- clearTimeout(timeoutToken);
90
- socket.removeEventListener("error", onError);
91
- socket.removeEventListener("open", onOpen);
92
- };
93
- socket.addEventListener("open", onOpen);
94
- socket.addEventListener("error", onError);
95
- disconnect = () => {
96
- onError(null);
97
- };
98
- });
99
- onStatusChanged(
100
- status = {
101
- type: WsEvent.CONNECTED,
102
- uri,
103
- protocols
104
- }
105
- );
106
- return (onMessage, onHalt) => {
107
- const _onMessage = (e) => {
108
- if (typeof e.data === "string") onMessage(e.data);
109
- };
110
- const innerHalt = (reason) => (e) => {
111
- console.warn(`WS halt (${reason})`);
112
- onStatusChanged(
113
- status = {
114
- type: reason,
115
- event: e
116
- }
117
- );
118
- onHalt();
119
- };
120
- const onError = innerHalt(WsEvent.ERROR);
121
- const onClose = innerHalt(WsEvent.CLOSE);
122
- socket.addEventListener("message", _onMessage);
123
- socket.addEventListener("error", onError);
124
- socket.addEventListener("close", onClose);
125
- disconnect = (withHalt) => {
126
- disconnect = noop;
127
- socket.removeEventListener("message", _onMessage);
128
- socket.removeEventListener("error", onError);
129
- socket.removeEventListener("close", onClose);
130
- forceSocketClose();
131
- if (withHalt) onClose({});
110
+ let outerCleanup = noop;
111
+ const result = followEnhancer(
112
+ jsonRpcProviderProxy.getSyncProvider(async () => {
113
+ const [uri, protocols] = switchTo || endpoints[idx++ % endpoints.length];
114
+ switchTo = null;
115
+ const socket = new WebsocketClass(uri, protocols);
116
+ const forceSocketClose = () => {
117
+ try {
118
+ socket.addEventListener("error", noop, { once: true });
119
+ socket.close();
120
+ } catch {
121
+ }
132
122
  };
133
- return {
134
- send: (msg) => {
135
- socket.send(msg);
136
- },
137
- disconnect
123
+ onStatusChanged(
124
+ status = {
125
+ type: WsEvent.CONNECTING,
126
+ uri,
127
+ protocols
128
+ }
129
+ );
130
+ await new Promise((resolve, reject) => {
131
+ const onOpen = () => {
132
+ initialCleanup();
133
+ resolve();
134
+ };
135
+ const onError = (e) => {
136
+ initialCleanup();
137
+ if (e == null) forceSocketClose();
138
+ console.error(
139
+ `Unable to connect to ${uri}${protocols ? ", protocols: " + protocols : ""}`
140
+ );
141
+ onStatusChanged(
142
+ status = {
143
+ type: e ? WsEvent.ERROR : WsEvent.CLOSE,
144
+ event: e
145
+ }
146
+ );
147
+ setTimeout(reject, e ? 300 : 0, e);
148
+ };
149
+ const timeoutToken = timeout !== Infinity ? setTimeout(() => {
150
+ initialCleanup();
151
+ forceSocketClose();
152
+ onStatusChanged(status = timeoutError);
153
+ reject(timeoutError.event);
154
+ }, timeout) : void 0;
155
+ const initialCleanup = () => {
156
+ clearTimeout(timeoutToken);
157
+ socket.removeEventListener("error", onError);
158
+ socket.removeEventListener("open", onOpen);
159
+ };
160
+ socket.addEventListener("open", onOpen);
161
+ socket.addEventListener("error", onError);
162
+ disconnect = () => {
163
+ onError(null);
164
+ };
165
+ });
166
+ onStatusChanged(
167
+ status = {
168
+ type: WsEvent.CONNECTED,
169
+ uri,
170
+ protocols
171
+ }
172
+ );
173
+ return (onMessage, onHalt) => {
174
+ const _onMessage = (e) => {
175
+ if (typeof e.data === "string") onMessage(e.data);
176
+ };
177
+ const innerHalt = (reason) => (e) => {
178
+ console.warn(`WS halt (${reason})`);
179
+ onStatusChanged(
180
+ status = {
181
+ type: reason,
182
+ event: e
183
+ }
184
+ );
185
+ onHalt();
186
+ };
187
+ const onError = innerHalt(WsEvent.ERROR);
188
+ const onClose = innerHalt(WsEvent.CLOSE);
189
+ socket.addEventListener("message", _onMessage);
190
+ socket.addEventListener("error", onError);
191
+ socket.addEventListener("close", onClose);
192
+ disconnect = (withHalt) => {
193
+ outerCleanup();
194
+ disconnect = noop;
195
+ socket.removeEventListener("message", _onMessage);
196
+ socket.removeEventListener("error", onError);
197
+ socket.removeEventListener("close", onClose);
198
+ forceSocketClose();
199
+ if (withHalt) onClose({});
200
+ };
201
+ return {
202
+ send: (msg) => {
203
+ socket.send(msg);
204
+ },
205
+ disconnect
206
+ };
138
207
  };
139
- };
140
- });
141
- result.getStatus = () => status;
142
- result.switch = (...args2) => {
208
+ }),
209
+ () => {
210
+ switchFn();
211
+ }
212
+ );
213
+ outerCleanup = result.cleanup;
214
+ delete result.cleanup;
215
+ const switchFn = (...args2) => {
143
216
  if (status.type === WsEvent.CLOSE) return;
144
217
  if (args2.length) switchTo = args2;
145
218
  if (status.type !== WsEvent.ERROR) disconnect(true);
146
219
  };
147
- return result;
220
+ return Object.assign(result, { switch: switchFn, getStatus: () => status });
148
221
  };
149
222
  };
150
223