@qevm/providers 1.0.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 (114) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +78 -0
  3. package/lib/_version.d.ts +2 -0
  4. package/lib/_version.d.ts.map +1 -0
  5. package/lib/_version.js +5 -0
  6. package/lib/_version.js.map +1 -0
  7. package/lib/alchemy-provider.d.ts +17 -0
  8. package/lib/alchemy-provider.d.ts.map +1 -0
  9. package/lib/alchemy-provider.js +112 -0
  10. package/lib/alchemy-provider.js.map +1 -0
  11. package/lib/ankr-provider.d.ts +10 -0
  12. package/lib/ankr-provider.d.ts.map +1 -0
  13. package/lib/ankr-provider.js +79 -0
  14. package/lib/ankr-provider.js.map +1 -0
  15. package/lib/base-provider.d.ts +156 -0
  16. package/lib/base-provider.d.ts.map +1 -0
  17. package/lib/base-provider.js +2585 -0
  18. package/lib/base-provider.js.map +1 -0
  19. package/lib/browser-ipc-provider.d.ts +3 -0
  20. package/lib/browser-ipc-provider.d.ts.map +1 -0
  21. package/lib/browser-ipc-provider.js +6 -0
  22. package/lib/browser-ipc-provider.js.map +1 -0
  23. package/lib/browser-net.d.ts +2 -0
  24. package/lib/browser-net.d.ts.map +1 -0
  25. package/lib/browser-net.js +6 -0
  26. package/lib/browser-net.js.map +1 -0
  27. package/lib/browser-ws.d.ts +3 -0
  28. package/lib/browser-ws.d.ts.map +1 -0
  29. package/lib/browser-ws.js +22 -0
  30. package/lib/browser-ws.js.map +1 -0
  31. package/lib/cloudflare-provider.d.ts +8 -0
  32. package/lib/cloudflare-provider.d.ts.map +1 -0
  33. package/lib/cloudflare-provider.js +100 -0
  34. package/lib/cloudflare-provider.js.map +1 -0
  35. package/lib/etherscan-provider.d.ts +18 -0
  36. package/lib/etherscan-provider.d.ts.map +1 -0
  37. package/lib/etherscan-provider.js +528 -0
  38. package/lib/etherscan-provider.js.map +1 -0
  39. package/lib/fallback-provider.d.ts +20 -0
  40. package/lib/fallback-provider.d.ts.map +1 -0
  41. package/lib/fallback-provider.js +699 -0
  42. package/lib/fallback-provider.js.map +1 -0
  43. package/lib/formatter.d.ts +60 -0
  44. package/lib/formatter.d.ts.map +1 -0
  45. package/lib/formatter.js +452 -0
  46. package/lib/formatter.js.map +1 -0
  47. package/lib/index.d.ts +23 -0
  48. package/lib/index.d.ts.map +1 -0
  49. package/lib/index.js +97 -0
  50. package/lib/index.js.map +1 -0
  51. package/lib/infura-provider.d.ts +21 -0
  52. package/lib/infura-provider.d.ts.map +1 -0
  53. package/lib/infura-provider.js +141 -0
  54. package/lib/infura-provider.js.map +1 -0
  55. package/lib/ipc-provider.d.ts +8 -0
  56. package/lib/ipc-provider.d.ts.map +1 -0
  57. package/lib/ipc-provider.js +77 -0
  58. package/lib/ipc-provider.js.map +1 -0
  59. package/lib/json-rpc-batch-provider.d.ts +17 -0
  60. package/lib/json-rpc-batch-provider.d.ts.map +1 -0
  61. package/lib/json-rpc-batch-provider.js +99 -0
  62. package/lib/json-rpc-batch-provider.js.map +1 -0
  63. package/lib/json-rpc-provider.d.ts +54 -0
  64. package/lib/json-rpc-provider.d.ts.map +1 -0
  65. package/lib/json-rpc-provider.js +855 -0
  66. package/lib/json-rpc-provider.js.map +1 -0
  67. package/lib/nodesmith-provider.d.ts +7 -0
  68. package/lib/nodesmith-provider.d.ts.map +1 -0
  69. package/lib/nodesmith-provider.js +64 -0
  70. package/lib/nodesmith-provider.js.map +1 -0
  71. package/lib/pocket-provider.d.ts +12 -0
  72. package/lib/pocket-provider.d.ts.map +1 -0
  73. package/lib/pocket-provider.js +98 -0
  74. package/lib/pocket-provider.js.map +1 -0
  75. package/lib/url-json-rpc-provider.d.ts +18 -0
  76. package/lib/url-json-rpc-provider.d.ts.map +1 -0
  77. package/lib/url-json-rpc-provider.js +153 -0
  78. package/lib/url-json-rpc-provider.js.map +1 -0
  79. package/lib/web3-provider.d.ts +28 -0
  80. package/lib/web3-provider.d.ts.map +1 -0
  81. package/lib/web3-provider.js +155 -0
  82. package/lib/web3-provider.js.map +1 -0
  83. package/lib/websocket-provider.d.ts +48 -0
  84. package/lib/websocket-provider.d.ts.map +1 -0
  85. package/lib/websocket-provider.js +384 -0
  86. package/lib/websocket-provider.js.map +1 -0
  87. package/lib/ws.d.ts +3 -0
  88. package/lib/ws.d.ts.map +1 -0
  89. package/lib/ws.js +9 -0
  90. package/lib/ws.js.map +1 -0
  91. package/package.json +57 -0
  92. package/src.ts/_version.ts +1 -0
  93. package/src.ts/alchemy-provider.ts +101 -0
  94. package/src.ts/ankr-provider.ts +68 -0
  95. package/src.ts/base-provider.ts +2216 -0
  96. package/src.ts/browser-ipc-provider.ts +7 -0
  97. package/src.ts/browser-net.ts +3 -0
  98. package/src.ts/browser-ws.ts +21 -0
  99. package/src.ts/cloudflare-provider.ts +42 -0
  100. package/src.ts/etherscan-provider.ts +454 -0
  101. package/src.ts/fallback-provider.ts +654 -0
  102. package/src.ts/formatter.ts +522 -0
  103. package/src.ts/index.ts +178 -0
  104. package/src.ts/infura-provider.ts +143 -0
  105. package/src.ts/ipc-provider.ts +72 -0
  106. package/src.ts/json-rpc-batch-provider.ts +97 -0
  107. package/src.ts/json-rpc-provider.ts +742 -0
  108. package/src.ts/nodesmith-provider.ts +50 -0
  109. package/src.ts/pocket-provider.ts +93 -0
  110. package/src.ts/url-json-rpc-provider.ts +106 -0
  111. package/src.ts/web3-provider.ts +169 -0
  112. package/src.ts/websocket-provider.ts +350 -0
  113. package/src.ts/ws.ts +3 -0
  114. package/thirdparty.d.ts +10 -0
@@ -0,0 +1,350 @@
1
+ "use strict";
2
+
3
+ import { BigNumber } from "@ethersproject/bignumber";
4
+ import { Network, Networkish } from "@ethersproject/networks";
5
+ import { defineReadOnly } from "@ethersproject/properties";
6
+
7
+ import { Event } from "./base-provider";
8
+ import { JsonRpcProvider } from "./json-rpc-provider";
9
+ import { WebSocket } from "./ws";
10
+
11
+ import { Logger } from "@ethersproject/logger";
12
+ import { version } from "./_version";
13
+ const logger = new Logger(version);
14
+
15
+ /**
16
+ * Notes:
17
+ *
18
+ * This provider differs a bit from the polling providers. One main
19
+ * difference is how it handles consistency. The polling providers
20
+ * will stall responses to ensure a consistent state, while this
21
+ * WebSocket provider assumes the connected backend will manage this.
22
+ *
23
+ * For example, if a polling provider emits an event which indicates
24
+ * the event occurred in blockhash XXX, a call to fetch that block by
25
+ * its hash XXX, if not present will retry until it is present. This
26
+ * can occur when querying a pool of nodes that are mildly out of sync
27
+ * with each other.
28
+ */
29
+
30
+ let NextId = 1;
31
+
32
+ export type InflightRequest = {
33
+ callback: (error: Error, result: any) => void;
34
+ payload: string;
35
+ };
36
+
37
+ export type Subscription = {
38
+ tag: string;
39
+ processFunc: (payload: any) => void;
40
+ };
41
+
42
+ export interface WebSocketLike {
43
+ onopen: ((...args: Array<any>) => any) | null;
44
+ onmessage: ((...args: Array<any>) => any) | null;
45
+ onerror: ((...args: Array<any>) => any) | null;
46
+
47
+ readyState: number;
48
+
49
+ send(payload: any): void;
50
+ close(code?: number, reason?: string): void;
51
+ }
52
+
53
+ // For more info about the Real-time Event API see:
54
+ // https://geth.ethereum.org/docs/rpc/pubsub
55
+
56
+ export class WebSocketProvider extends JsonRpcProvider {
57
+ readonly _websocket: any;
58
+ readonly _requests: { [ name: string ]: InflightRequest };
59
+ readonly _detectNetwork: Promise<Network>;
60
+
61
+ // Maps event tag to subscription ID (we dedupe identical events)
62
+ readonly _subIds: { [ tag: string ]: Promise<string> };
63
+
64
+ // Maps Subscription ID to Subscription
65
+ readonly _subs: { [ name: string ]: Subscription };
66
+
67
+ _wsReady: boolean;
68
+
69
+ constructor(url: string | WebSocketLike, network?: Networkish) {
70
+
71
+ // This will be added in the future; please open an issue to expedite
72
+ if (network === "any") {
73
+ logger.throwError("WebSocketProvider does not support 'any' network yet", Logger.errors.UNSUPPORTED_OPERATION, {
74
+ operation: "network:any"
75
+ });
76
+ }
77
+
78
+ if (typeof(url) === "string") {
79
+ super(url, network);
80
+ } else {
81
+ super("_websocket", network);
82
+ }
83
+
84
+ this._pollingInterval = -1;
85
+
86
+ this._wsReady = false;
87
+
88
+ if (typeof(url) === "string") {
89
+ defineReadOnly(this, "_websocket", new WebSocket(this.connection.url));
90
+ } else {
91
+ defineReadOnly(this, "_websocket", url);
92
+ }
93
+
94
+ defineReadOnly(this, "_requests", { });
95
+ defineReadOnly(this, "_subs", { });
96
+ defineReadOnly(this, "_subIds", { });
97
+ defineReadOnly(this, "_detectNetwork", super.detectNetwork());
98
+
99
+ // Stall sending requests until the socket is open...
100
+ this.websocket.onopen = () => {
101
+ this._wsReady = true;
102
+ Object.keys(this._requests).forEach((id) => {
103
+ this.websocket.send(this._requests[id].payload);
104
+ });
105
+ };
106
+
107
+ this.websocket.onmessage = (messageEvent: { data: string }) => {
108
+ const data = messageEvent.data;
109
+ const result = JSON.parse(data);
110
+ if (result.id != null) {
111
+ const id = String(result.id);
112
+ const request = this._requests[id];
113
+ delete this._requests[id];
114
+
115
+ if (result.result !== undefined) {
116
+ request.callback(null, result.result);
117
+
118
+ this.emit("debug", {
119
+ action: "response",
120
+ request: JSON.parse(request.payload),
121
+ response: result.result,
122
+ provider: this
123
+ });
124
+
125
+ } else {
126
+ let error: Error = null;
127
+ if (result.error) {
128
+ error = new Error(result.error.message || "unknown error");
129
+ defineReadOnly(<any>error, "code", result.error.code || null);
130
+ defineReadOnly(<any>error, "response", data);
131
+ } else {
132
+ error = new Error("unknown error");
133
+ }
134
+
135
+ request.callback(error, undefined);
136
+
137
+ this.emit("debug", {
138
+ action: "response",
139
+ error: error,
140
+ request: JSON.parse(request.payload),
141
+ provider: this
142
+ });
143
+
144
+ }
145
+
146
+ } else if (result.method === "eth_subscription") {
147
+ // Subscription...
148
+ const sub = this._subs[result.params.subscription];
149
+ if (sub) {
150
+ //this.emit.apply(this, );
151
+ sub.processFunc(result.params.result)
152
+ }
153
+
154
+ } else {
155
+ console.warn("this should not happen");
156
+ }
157
+ };
158
+
159
+ // This Provider does not actually poll, but we want to trigger
160
+ // poll events for things that depend on them (like stalling for
161
+ // block and transaction lookups)
162
+ const fauxPoll = setInterval(() => {
163
+ this.emit("poll");
164
+ }, 1000);
165
+ if (fauxPoll.unref) { fauxPoll.unref(); }
166
+ }
167
+
168
+ // Cannot narrow the type of _websocket, as that is not backwards compatible
169
+ // so we add a getter and let the WebSocket be a public API.
170
+ get websocket(): WebSocketLike { return this._websocket; }
171
+
172
+ detectNetwork(): Promise<Network> {
173
+ return this._detectNetwork;
174
+ }
175
+
176
+ get pollingInterval(): number {
177
+ return 0;
178
+ }
179
+
180
+ resetEventsBlock(blockNumber: number): void {
181
+ logger.throwError("cannot reset events block on WebSocketProvider", Logger.errors.UNSUPPORTED_OPERATION, {
182
+ operation: "resetEventBlock"
183
+ });
184
+ }
185
+
186
+ set pollingInterval(value: number) {
187
+ logger.throwError("cannot set polling interval on WebSocketProvider", Logger.errors.UNSUPPORTED_OPERATION, {
188
+ operation: "setPollingInterval"
189
+ });
190
+ }
191
+
192
+ async poll(): Promise<void> {
193
+ return null;
194
+ }
195
+
196
+ set polling(value: boolean) {
197
+ if (!value) { return; }
198
+
199
+ logger.throwError("cannot set polling on WebSocketProvider", Logger.errors.UNSUPPORTED_OPERATION, {
200
+ operation: "setPolling"
201
+ });
202
+ }
203
+
204
+ send(method: string, params?: Array<any>): Promise<any> {
205
+ const rid = NextId++;
206
+
207
+ return new Promise((resolve, reject) => {
208
+ function callback(error: Error, result: any) {
209
+ if (error) { return reject(error); }
210
+ return resolve(result);
211
+ }
212
+
213
+ const payload = JSON.stringify({
214
+ method: method,
215
+ params: params,
216
+ id: rid,
217
+ jsonrpc: "2.0"
218
+ });
219
+
220
+ this.emit("debug", {
221
+ action: "request",
222
+ request: JSON.parse(payload),
223
+ provider: this
224
+ });
225
+
226
+ this._requests[String(rid)] = { callback, payload };
227
+
228
+ if (this._wsReady) { this.websocket.send(payload); }
229
+ });
230
+ }
231
+
232
+ static defaultUrl(): string {
233
+ return "ws:/\/localhost:8546";
234
+ }
235
+
236
+ async _subscribe(tag: string, param: Array<any>, processFunc: (result: any) => void): Promise<void> {
237
+ let subIdPromise = this._subIds[tag];
238
+ if (subIdPromise == null) {
239
+ subIdPromise = Promise.all(param).then((param) => {
240
+ return this.send("eth_subscribe", param);
241
+ });
242
+ this._subIds[tag] = subIdPromise;
243
+ }
244
+ const subId = await subIdPromise;
245
+ this._subs[subId] = { tag, processFunc };
246
+ }
247
+
248
+ _startEvent(event: Event): void {
249
+ switch (event.type) {
250
+ case "block":
251
+ this._subscribe("block", [ "newHeads" ], (result: any) => {
252
+ const blockNumber = BigNumber.from(result.number).toNumber();
253
+ this._emitted.block = blockNumber;
254
+ this.emit("block", blockNumber);
255
+ });
256
+ break;
257
+
258
+ case "pending":
259
+ this._subscribe("pending", [ "newPendingTransactions" ], (result: any) => {
260
+ this.emit("pending", result);
261
+ });
262
+ break;
263
+
264
+ case "filter":
265
+ this._subscribe(event.tag, [ "logs", this._getFilter(event.filter) ], (result: any) => {
266
+ if (result.removed == null) { result.removed = false; }
267
+ this.emit(event.filter, this.formatter.filterLog(result));
268
+ });
269
+ break;
270
+
271
+ case "tx": {
272
+ const emitReceipt = (event: Event) => {
273
+ const hash = event.hash;
274
+ this.getTransactionReceipt(hash).then((receipt) => {
275
+ if (!receipt) { return; }
276
+ this.emit(hash, receipt);
277
+ });
278
+ };
279
+
280
+ // In case it is already mined
281
+ emitReceipt(event);
282
+
283
+ // To keep things simple, we start up a single newHeads subscription
284
+ // to keep an eye out for transactions we are watching for.
285
+ // Starting a subscription for an event (i.e. "tx") that is already
286
+ // running is (basically) a nop.
287
+ this._subscribe("tx", [ "newHeads" ], (result: any) => {
288
+ this._events.filter((e) => (e.type === "tx")).forEach(emitReceipt);
289
+ });
290
+ break;
291
+ }
292
+
293
+ // Nothing is needed
294
+ case "debug":
295
+ case "poll":
296
+ case "willPoll":
297
+ case "didPoll":
298
+ case "error":
299
+ break;
300
+
301
+ default:
302
+ console.log("unhandled:", event);
303
+ break;
304
+ }
305
+ }
306
+
307
+ _stopEvent(event: Event): void {
308
+ let tag = event.tag;
309
+
310
+ if (event.type === "tx") {
311
+ // There are remaining transaction event listeners
312
+ if (this._events.filter((e) => (e.type === "tx")).length) {
313
+ return;
314
+ }
315
+ tag = "tx";
316
+ } else if (this.listenerCount(event.event)) {
317
+ // There are remaining event listeners
318
+ return;
319
+ }
320
+
321
+ const subId = this._subIds[tag];
322
+ if (!subId) { return; }
323
+
324
+ delete this._subIds[tag];
325
+ subId.then((subId) => {
326
+ if (!this._subs[subId]) { return; }
327
+ delete this._subs[subId];
328
+ this.send("eth_unsubscribe", [ subId ]);
329
+ });
330
+ }
331
+
332
+ async destroy(): Promise<void> {
333
+ // Wait until we have connected before trying to disconnect
334
+ if (this.websocket.readyState === WebSocket.CONNECTING) {
335
+ await (new Promise((resolve) => {
336
+ this.websocket.onopen = function() {
337
+ resolve(true);
338
+ };
339
+
340
+ this.websocket.onerror = function() {
341
+ resolve(false);
342
+ };
343
+ }));
344
+ }
345
+
346
+ // Hangup
347
+ // See: https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes
348
+ this.websocket.close(1000);
349
+ }
350
+ }
package/src.ts/ws.ts ADDED
@@ -0,0 +1,3 @@
1
+ import WebSocket from "ws";
2
+
3
+ export { WebSocket }
@@ -0,0 +1,10 @@
1
+ declare module "ws" {
2
+ export interface WebSocker {
3
+ send(): void;
4
+ onopen: () => void;
5
+ onmessage: (messageEvent: { target: any, type: string, data: string }) => void
6
+ }
7
+
8
+ export default WebSocket;
9
+ }
10
+