@qevm/providers 1.0.2 → 1.0.3

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 (100) hide show
  1. package/README.md +3 -9
  2. package/lib/_version.d.ts +1 -1
  3. package/lib/_version.js +1 -1
  4. package/lib/base-provider.d.ts +2 -2
  5. package/lib/base-provider.d.ts.map +1 -1
  6. package/lib/base-provider.js +300 -145
  7. package/lib/base-provider.js.map +1 -1
  8. package/lib/browser-ipc-provider.d.ts.map +1 -1
  9. package/lib/browser-ipc-provider.js.map +1 -1
  10. package/lib/browser-net.d.ts.map +1 -1
  11. package/lib/browser-net.js.map +1 -1
  12. package/lib/browser-ws.d.ts.map +1 -1
  13. package/lib/browser-ws.js +2 -2
  14. package/lib/browser-ws.js.map +1 -1
  15. package/lib/fallback-provider.d.ts +1 -1
  16. package/lib/fallback-provider.d.ts.map +1 -1
  17. package/lib/fallback-provider.js +86 -55
  18. package/lib/fallback-provider.js.map +1 -1
  19. package/lib/formatter.d.ts.map +1 -1
  20. package/lib/formatter.js +35 -29
  21. package/lib/formatter.js.map +1 -1
  22. package/lib/index.d.ts +3 -10
  23. package/lib/index.d.ts.map +1 -1
  24. package/lib/index.js +5 -28
  25. package/lib/index.js.map +1 -1
  26. package/lib/ipc-provider.d.ts +1 -1
  27. package/lib/ipc-provider.d.ts.map +1 -1
  28. package/lib/ipc-provider.js +6 -4
  29. package/lib/ipc-provider.js.map +1 -1
  30. package/lib/json-rpc-batch-provider.d.ts.map +1 -1
  31. package/lib/json-rpc-batch-provider.js +6 -6
  32. package/lib/json-rpc-batch-provider.js.map +1 -1
  33. package/lib/json-rpc-provider.d.ts +2 -2
  34. package/lib/json-rpc-provider.d.ts.map +1 -1
  35. package/lib/json-rpc-provider.js +167 -69
  36. package/lib/json-rpc-provider.js.map +1 -1
  37. package/lib/url-json-rpc-provider.d.ts +1 -1
  38. package/lib/url-json-rpc-provider.d.ts.map +1 -1
  39. package/lib/url-json-rpc-provider.js +4 -4
  40. package/lib/url-json-rpc-provider.js.map +1 -1
  41. package/lib/web3-provider.d.ts +1 -2
  42. package/lib/web3-provider.d.ts.map +1 -1
  43. package/lib/web3-provider.js +11 -14
  44. package/lib/web3-provider.js.map +1 -1
  45. package/lib/websocket-provider.d.ts +1 -1
  46. package/lib/websocket-provider.d.ts.map +1 -1
  47. package/lib/websocket-provider.js +21 -17
  48. package/lib/websocket-provider.js.map +1 -1
  49. package/lib/ws.d.ts.map +1 -1
  50. package/package.json +61 -58
  51. package/src.ts/_version.ts +1 -1
  52. package/src.ts/base-provider.ts +1418 -645
  53. package/src.ts/browser-ipc-provider.ts +1 -3
  54. package/src.ts/browser-net.ts +1 -1
  55. package/src.ts/browser-ws.ts +14 -8
  56. package/src.ts/fallback-provider.ts +375 -198
  57. package/src.ts/formatter.ts +161 -81
  58. package/src.ts/index.ts +54 -68
  59. package/src.ts/ipc-provider.ts +8 -7
  60. package/src.ts/json-rpc-batch-provider.ts +48 -44
  61. package/src.ts/json-rpc-provider.ts +594 -245
  62. package/src.ts/url-json-rpc-provider.ts +34 -15
  63. package/src.ts/web3-provider.ts +87 -54
  64. package/src.ts/websocket-provider.ts +124 -66
  65. package/src.ts/ws.ts +1 -1
  66. package/lib/alchemy-provider.d.ts +0 -17
  67. package/lib/alchemy-provider.d.ts.map +0 -1
  68. package/lib/alchemy-provider.js +0 -88
  69. package/lib/alchemy-provider.js.map +0 -1
  70. package/lib/ankr-provider.d.ts +0 -10
  71. package/lib/ankr-provider.d.ts.map +0 -1
  72. package/lib/ankr-provider.js +0 -59
  73. package/lib/ankr-provider.js.map +0 -1
  74. package/lib/cloudflare-provider.d.ts +0 -8
  75. package/lib/cloudflare-provider.d.ts.map +0 -1
  76. package/lib/cloudflare-provider.js +0 -37
  77. package/lib/cloudflare-provider.js.map +0 -1
  78. package/lib/etherscan-provider.d.ts +0 -18
  79. package/lib/etherscan-provider.d.ts.map +0 -1
  80. package/lib/etherscan-provider.js +0 -408
  81. package/lib/etherscan-provider.js.map +0 -1
  82. package/lib/infura-provider.d.ts +0 -21
  83. package/lib/infura-provider.d.ts.map +0 -1
  84. package/lib/infura-provider.js +0 -117
  85. package/lib/infura-provider.js.map +0 -1
  86. package/lib/nodesmith-provider.d.ts +0 -7
  87. package/lib/nodesmith-provider.d.ts.map +0 -1
  88. package/lib/nodesmith-provider.js +0 -44
  89. package/lib/nodesmith-provider.js.map +0 -1
  90. package/lib/pocket-provider.d.ts +0 -12
  91. package/lib/pocket-provider.d.ts.map +0 -1
  92. package/lib/pocket-provider.js +0 -78
  93. package/lib/pocket-provider.js.map +0 -1
  94. package/src.ts/alchemy-provider.ts +0 -101
  95. package/src.ts/ankr-provider.ts +0 -68
  96. package/src.ts/cloudflare-provider.ts +0 -42
  97. package/src.ts/etherscan-provider.ts +0 -454
  98. package/src.ts/infura-provider.ts +0 -143
  99. package/src.ts/nodesmith-provider.ts +0 -50
  100. package/src.ts/pocket-provider.ts +0 -93
@@ -1,21 +1,27 @@
1
1
  "use strict";
2
2
 
3
- import { Block, BlockWithTransactions, Provider } from "@qevm/abstract-provider";
3
+ import {
4
+ Block,
5
+ BlockWithTransactions,
6
+ Provider,
7
+ } from "@qevm/abstract-provider";
4
8
  import { BigNumber } from "@qevm/bignumber";
5
9
  import { isHexString } from "@qevm/bytes";
6
- import { Network } from "@ethersproject/networks";
7
- import { deepCopy, defineReadOnly, shallowCopy } from "@ethersproject/properties";
10
+ import { Network } from "@qevm/networks";
11
+ import { deepCopy, defineReadOnly, shallowCopy } from "@qevm/properties";
8
12
  import { shuffled } from "@qevm/random";
9
13
  import { poll } from "@qevm/web";
10
14
 
11
15
  import { BaseProvider } from "./base-provider";
12
16
  import { isCommunityResource } from "./formatter";
13
17
 
14
- import { Logger } from "@ethersproject/logger";
18
+ import { Logger } from "@qevm/logger";
15
19
  import { version } from "./_version";
16
20
  const logger = new Logger(version);
17
21
 
18
- function now() { return (new Date()).getTime(); }
22
+ function now() {
23
+ return new Date().getTime();
24
+ }
19
25
 
20
26
  // Returns to network as long as all agree, or null if any is null.
21
27
  // Throws an error if any two networks do not match.
@@ -26,15 +32,27 @@ function checkNetworks(networks: Array<Network>): Network {
26
32
  const network = networks[i];
27
33
 
28
34
  // Null! We do not know our network; bail.
29
- if (network == null) { return null; }
35
+ if (network == null) {
36
+ return null;
37
+ }
30
38
 
31
39
  if (result) {
32
40
  // Make sure the network matches the previous networks
33
- if (!(result.name === network.name && result.chainId === network.chainId &&
34
- ((result.ensAddress === network.ensAddress) || (result.ensAddress == null && network.ensAddress == null)))) {
35
-
36
- logger.throwArgumentError("provider mismatch", "networks", networks);
37
- }
41
+ if (
42
+ !(
43
+ result.name === network.name &&
44
+ result.chainId === network.chainId &&
45
+ (result.ensAddress === network.ensAddress ||
46
+ (result.ensAddress == null &&
47
+ network.ensAddress == null))
48
+ )
49
+ ) {
50
+ logger.throwArgumentError(
51
+ "provider mismatch",
52
+ "networks",
53
+ networks,
54
+ );
55
+ }
38
56
  } else {
39
57
  result = network;
40
58
  }
@@ -53,7 +71,8 @@ function median(values: Array<number>, maxDelta?: number): number {
53
71
  }
54
72
 
55
73
  // Even length; take the average of the two middle
56
- const a = values[middle - 1], b = values[middle];
74
+ const a = values[middle - 1],
75
+ b = values[middle];
57
76
 
58
77
  if (maxDelta != null && Math.abs(a - b) > maxDelta) {
59
78
  return null;
@@ -65,35 +84,40 @@ function median(values: Array<number>, maxDelta?: number): number {
65
84
  function serialize(value: any): string {
66
85
  if (value === null) {
67
86
  return "null";
68
- } else if (typeof(value) === "number" || typeof(value) === "boolean") {
87
+ } else if (typeof value === "number" || typeof value === "boolean") {
69
88
  return JSON.stringify(value);
70
- } else if (typeof(value) === "string") {
89
+ } else if (typeof value === "string") {
71
90
  return value;
72
91
  } else if (BigNumber.isBigNumber(value)) {
73
92
  return value.toString();
74
93
  } else if (Array.isArray(value)) {
75
94
  return JSON.stringify(value.map((i) => serialize(i)));
76
- } else if (typeof(value) === "object") {
95
+ } else if (typeof value === "object") {
77
96
  const keys = Object.keys(value);
78
97
  keys.sort();
79
- return "{" + keys.map((key) => {
80
- let v = value[key];
81
- if (typeof(v) === "function") {
82
- v = "[function]";
83
- } else {
84
- v = serialize(v);
85
- }
86
- return JSON.stringify(key) + ":" + v;
87
- }).join(",") + "}";
98
+ return (
99
+ "{" +
100
+ keys
101
+ .map((key) => {
102
+ let v = value[key];
103
+ if (typeof v === "function") {
104
+ v = "[function]";
105
+ } else {
106
+ v = serialize(v);
107
+ }
108
+ return JSON.stringify(key) + ":" + v;
109
+ })
110
+ .join(",") +
111
+ "}"
112
+ );
88
113
  }
89
114
 
90
- throw new Error("unknown value type: " + typeof(value));
115
+ throw new Error("unknown value type: " + typeof value);
91
116
  }
92
117
 
93
118
  // Next request ID to use for emitting debug info
94
119
  let nextRid = 1;
95
120
 
96
-
97
121
  export interface FallbackProviderConfig {
98
122
  // The Provider
99
123
  provider: Provider;
@@ -112,35 +136,35 @@ export interface FallbackProviderConfig {
112
136
  // provider may be more reliable or trustworthy than others, but usually
113
137
  // this should be left as the default
114
138
  weight?: number;
115
- };
139
+ }
116
140
 
117
141
  // A Staller is used to provide a delay to give a Provider a chance to response
118
142
  // before asking the next Provider to try.
119
143
  type Staller = {
120
- wait: (func: () => void) => Promise<void>
121
- getPromise: () => Promise<void>,
122
- cancel: () => void
144
+ wait: (func: () => void) => Promise<void>;
145
+ getPromise: () => Promise<void>;
146
+ cancel: () => void;
123
147
  };
124
148
 
125
149
  function stall(duration: number): Staller {
126
150
  let cancel: () => void = null;
127
151
 
128
152
  let timer: NodeJS.Timeout = null;
129
- let promise = <Promise<void>>(new Promise((resolve) => {
130
- cancel = function() {
153
+ let promise = <Promise<void>>new Promise((resolve) => {
154
+ cancel = function () {
131
155
  if (timer) {
132
156
  clearTimeout(timer);
133
157
  timer = null;
134
158
  }
135
159
  resolve();
136
- }
160
+ };
137
161
  timer = setTimeout(cancel, duration);
138
- }));
162
+ });
139
163
 
140
164
  const wait = (func: () => void) => {
141
165
  promise = promise.then(func);
142
166
  return promise;
143
- }
167
+ };
144
168
 
145
169
  function getPromise(): Promise<void> {
146
170
  return promise;
@@ -154,7 +178,7 @@ const ForwardErrors = [
154
178
  Logger.errors.INSUFFICIENT_FUNDS,
155
179
  Logger.errors.NONCE_EXPIRED,
156
180
  Logger.errors.REPLACEMENT_UNDERPRICED,
157
- Logger.errors.UNPREDICTABLE_GAS_LIMIT
181
+ Logger.errors.UNPREDICTABLE_GAS_LIMIT,
158
182
  ];
159
183
 
160
184
  const ForwardProperties = [
@@ -166,7 +190,6 @@ const ForwardProperties = [
166
190
  "transaction",
167
191
  ];
168
192
 
169
-
170
193
  // @TODO: Make this an object with staller and cancel built-in
171
194
  interface RunningConfig extends FallbackProviderConfig {
172
195
  start?: number;
@@ -176,15 +199,19 @@ interface RunningConfig extends FallbackProviderConfig {
176
199
  staller?: Staller;
177
200
  result?: any;
178
201
  error?: Error;
179
- };
202
+ }
180
203
 
181
204
  function exposeDebugConfig(config: RunningConfig, now?: number): any {
182
205
  const result: any = {
183
- weight: config.weight
206
+ weight: config.weight,
184
207
  };
185
208
  Object.defineProperty(result, "provider", { get: () => config.provider });
186
- if (config.start) { result.start = config.start; }
187
- if (now) { result.duration = (now - config.start); }
209
+ if (config.start) {
210
+ result.start = config.start;
211
+ }
212
+ if (now) {
213
+ result.duration = now - config.start;
214
+ }
188
215
  if (config.done) {
189
216
  if (config.error) {
190
217
  result.error = config.error;
@@ -195,14 +222,18 @@ function exposeDebugConfig(config: RunningConfig, now?: number): any {
195
222
  return result;
196
223
  }
197
224
 
198
- function normalizedTally(normalize: (value: any) => string, quorum: number): (configs: Array<RunningConfig>) => any {
199
- return function(configs: Array<RunningConfig>): any {
200
-
225
+ function normalizedTally(
226
+ normalize: (value: any) => string,
227
+ quorum: number,
228
+ ): (configs: Array<RunningConfig>) => any {
229
+ return function (configs: Array<RunningConfig>): any {
201
230
  // Count the votes for each result
202
- const tally: { [ key: string]: { count: number, result: any } } = { };
231
+ const tally: { [key: string]: { count: number; result: any } } = {};
203
232
  configs.forEach((c) => {
204
233
  const value = normalize(c.result);
205
- if (!tally[value]) { tally[value] = { count: 0, result: c.result }; }
234
+ if (!tally[value]) {
235
+ tally[value] = { count: 0, result: c.result };
236
+ }
206
237
  tally[value].count++;
207
238
  });
208
239
 
@@ -217,10 +248,13 @@ function normalizedTally(normalize: (value: any) => string, quorum: number): (co
217
248
 
218
249
  // No quroum
219
250
  return undefined;
220
- }
251
+ };
221
252
  }
222
- function getProcessFunc(provider: FallbackProvider, method: string, params: { [ key: string ]: any }): (configs: Array<RunningConfig>) => any {
223
-
253
+ function getProcessFunc(
254
+ provider: FallbackProvider,
255
+ method: string,
256
+ params: { [key: string]: any },
257
+ ): (configs: Array<RunningConfig>) => any {
224
258
  let normalize = serialize;
225
259
 
226
260
  switch (method) {
@@ -229,17 +263,24 @@ function getProcessFunc(provider: FallbackProvider, method: string, params: { [
229
263
  // present, in which case that is probably true and the median
230
264
  // is going to be stale soon. In the event of a malicious node,
231
265
  // the lie will be true soon enough.
232
- return function(configs: Array<RunningConfig>): number {
266
+ return function (configs: Array<RunningConfig>): number {
233
267
  const values = configs.map((c) => c.result);
234
268
 
235
269
  // Get the median block number
236
- let blockNumber = median(configs.map((c) => c.result), 2);
237
- if (blockNumber == null) { return undefined; }
270
+ let blockNumber = median(
271
+ configs.map((c) => c.result),
272
+ 2,
273
+ );
274
+ if (blockNumber == null) {
275
+ return undefined;
276
+ }
238
277
 
239
278
  blockNumber = Math.ceil(blockNumber);
240
279
 
241
280
  // If the next block height is present, its prolly safe to use
242
- if (values.indexOf(blockNumber + 1) >= 0) { blockNumber++; }
281
+ if (values.indexOf(blockNumber + 1) >= 0) {
282
+ blockNumber++;
283
+ }
243
284
 
244
285
  // Don't ever roll back the blockNumber
245
286
  if (blockNumber >= provider._highestBlockNumber) {
@@ -253,18 +294,18 @@ function getProcessFunc(provider: FallbackProvider, method: string, params: { [
253
294
  // Return the middle (round index up) value, similar to median
254
295
  // but do not average even entries and choose the higher.
255
296
  // Malicious actors must compromise 50% of the nodes to lie.
256
- return function(configs: Array<RunningConfig>): BigNumber {
297
+ return function (configs: Array<RunningConfig>): BigNumber {
257
298
  const values = configs.map((c) => c.result);
258
299
  values.sort();
259
300
  return values[Math.floor(values.length / 2)];
260
- }
301
+ };
261
302
 
262
303
  case "getEtherPrice":
263
304
  // Returns the median price. Malicious actors must compromise at
264
305
  // least 50% of the nodes to lie (in a meaningful way).
265
- return function(configs: Array<RunningConfig>): number {
306
+ return function (configs: Array<RunningConfig>): number {
266
307
  return median(configs.map((c) => c.result));
267
- }
308
+ };
268
309
 
269
310
  // No additional normalizing required; serialize is enough
270
311
  case "getBalance":
@@ -279,21 +320,25 @@ function getProcessFunc(provider: FallbackProvider, method: string, params: { [
279
320
  // We drop the confirmations from transactions as it is approximate
280
321
  case "getTransaction":
281
322
  case "getTransactionReceipt":
282
- normalize = function(tx: any): string {
283
- if (tx == null) { return null; }
323
+ normalize = function (tx: any): string {
324
+ if (tx == null) {
325
+ return null;
326
+ }
284
327
 
285
328
  tx = shallowCopy(tx);
286
329
  tx.confirmations = -1;
287
330
  return serialize(tx);
288
- }
331
+ };
289
332
  break;
290
333
 
291
334
  // We drop the confirmations from transactions as it is approximate
292
335
  case "getBlock":
293
336
  // We drop the confirmations from transactions as it is approximate
294
337
  if (params.includeTransactions) {
295
- normalize = function(block: BlockWithTransactions): string {
296
- if (block == null) { return null; }
338
+ normalize = function (block: BlockWithTransactions): string {
339
+ if (block == null) {
340
+ return null;
341
+ }
297
342
 
298
343
  block = shallowCopy(block);
299
344
  block.transactions = block.transactions.map((tx) => {
@@ -304,10 +349,12 @@ function getProcessFunc(provider: FallbackProvider, method: string, params: { [
304
349
  return serialize(block);
305
350
  };
306
351
  } else {
307
- normalize = function(block: Block): string {
308
- if (block == null) { return null; }
352
+ normalize = function (block: Block): string {
353
+ if (block == null) {
354
+ return null;
355
+ }
309
356
  return serialize(block);
310
- }
357
+ };
311
358
  }
312
359
  break;
313
360
 
@@ -318,36 +365,52 @@ function getProcessFunc(provider: FallbackProvider, method: string, params: { [
318
365
  // Return the result if and only if the expected quorum is
319
366
  // satisfied and agreed upon for the final result.
320
367
  return normalizedTally(normalize, provider.quorum);
321
-
322
368
  }
323
369
 
324
370
  // If we are doing a blockTag query, we need to make sure the backend is
325
371
  // caught up to the FallbackProvider, before sending a request to it.
326
- async function waitForSync(config: RunningConfig, blockNumber: number): Promise<BaseProvider> {
327
- const provider = <BaseProvider>(config.provider);
328
-
329
- if ((provider.blockNumber != null && provider.blockNumber >= blockNumber) || blockNumber === -1) {
372
+ async function waitForSync(
373
+ config: RunningConfig,
374
+ blockNumber: number,
375
+ ): Promise<BaseProvider> {
376
+ const provider = <BaseProvider>config.provider;
377
+
378
+ if (
379
+ (provider.blockNumber != null && provider.blockNumber >= blockNumber) ||
380
+ blockNumber === -1
381
+ ) {
330
382
  return provider;
331
383
  }
332
384
 
333
- return poll(() => {
334
- return new Promise((resolve, reject) => {
335
- setTimeout(function() {
336
-
337
- // We are synced
338
- if (provider.blockNumber >= blockNumber) { return resolve(provider); }
385
+ return poll(
386
+ () => {
387
+ return new Promise((resolve, reject) => {
388
+ setTimeout(function () {
389
+ // We are synced
390
+ if (provider.blockNumber >= blockNumber) {
391
+ return resolve(provider);
392
+ }
339
393
 
340
- // We're done; just quit
341
- if (config.cancelled) { return resolve(null); }
394
+ // We're done; just quit
395
+ if (config.cancelled) {
396
+ return resolve(null);
397
+ }
342
398
 
343
- // Try again, next block
344
- return resolve(undefined);
345
- }, 0);
346
- });
347
- }, { oncePoll: provider });
399
+ // Try again, next block
400
+ return resolve(undefined);
401
+ }, 0);
402
+ });
403
+ },
404
+ { oncePoll: provider },
405
+ );
348
406
  }
349
407
 
350
- async function getRunner(config: RunningConfig, currentBlockNumber: number, method: string, params: { [ key: string]: any }): Promise<any> {
408
+ async function getRunner(
409
+ config: RunningConfig,
410
+ currentBlockNumber: number,
411
+ method: string,
412
+ params: { [key: string]: any },
413
+ ): Promise<any> {
351
414
  let provider = config.provider;
352
415
 
353
416
  switch (method) {
@@ -363,23 +426,34 @@ async function getRunner(config: RunningConfig, currentBlockNumber: number, meth
363
426
  case "getTransactionCount":
364
427
  case "getCode":
365
428
  if (params.blockTag && isHexString(params.blockTag)) {
366
- provider = await waitForSync(config, currentBlockNumber)
429
+ provider = await waitForSync(config, currentBlockNumber);
367
430
  }
368
- return provider[method](params.address, params.blockTag || "latest");
431
+ return provider[method](
432
+ params.address,
433
+ params.blockTag || "latest",
434
+ );
369
435
  case "getStorageAt":
370
436
  if (params.blockTag && isHexString(params.blockTag)) {
371
- provider = await waitForSync(config, currentBlockNumber)
437
+ provider = await waitForSync(config, currentBlockNumber);
372
438
  }
373
- return provider.getStorageAt(params.address, params.position, params.blockTag || "latest");
439
+ return provider.getStorageAt(
440
+ params.address,
441
+ params.position,
442
+ params.blockTag || "latest",
443
+ );
374
444
  case "getBlock":
375
445
  if (params.blockTag && isHexString(params.blockTag)) {
376
- provider = await waitForSync(config, currentBlockNumber)
446
+ provider = await waitForSync(config, currentBlockNumber);
377
447
  }
378
- return provider[(params.includeTransactions ? "getBlockWithTransactions": "getBlock")](params.blockTag || params.blockHash);
448
+ return provider[
449
+ params.includeTransactions
450
+ ? "getBlockWithTransactions"
451
+ : "getBlock"
452
+ ](params.blockTag || params.blockHash);
379
453
  case "call":
380
454
  case "estimateGas":
381
455
  if (params.blockTag && isHexString(params.blockTag)) {
382
- provider = await waitForSync(config, currentBlockNumber)
456
+ provider = await waitForSync(config, currentBlockNumber);
383
457
  }
384
458
  if (method === "call" && params.blockTag) {
385
459
  return provider[method](params.transaction, params.blockTag);
@@ -390,17 +464,24 @@ async function getRunner(config: RunningConfig, currentBlockNumber: number, meth
390
464
  return provider[method](params.transactionHash);
391
465
  case "getLogs": {
392
466
  let filter = params.filter;
393
- if ((filter.fromBlock && isHexString(filter.fromBlock)) || (filter.toBlock && isHexString(filter.toBlock))) {
394
- provider = await waitForSync(config, currentBlockNumber)
467
+ if (
468
+ (filter.fromBlock && isHexString(filter.fromBlock)) ||
469
+ (filter.toBlock && isHexString(filter.toBlock))
470
+ ) {
471
+ provider = await waitForSync(config, currentBlockNumber);
395
472
  }
396
473
  return provider.getLogs(filter);
397
474
  }
398
475
  }
399
476
 
400
- return logger.throwError("unknown method error", Logger.errors.UNKNOWN_ERROR, {
401
- method: method,
402
- params: params
403
- });
477
+ return logger.throwError(
478
+ "unknown method error",
479
+ Logger.errors.UNKNOWN_ERROR,
480
+ {
481
+ method: method,
482
+ params: params,
483
+ },
484
+ );
404
485
  }
405
486
 
406
487
  export class FallbackProvider extends BaseProvider {
@@ -412,44 +493,77 @@ export class FallbackProvider extends BaseProvider {
412
493
  // sample of backends
413
494
  _highestBlockNumber: number;
414
495
 
415
- constructor(providers: Array<Provider | FallbackProviderConfig>, quorum?: number) {
496
+ constructor(
497
+ providers: Array<Provider | FallbackProviderConfig>,
498
+ quorum?: number,
499
+ ) {
416
500
  if (providers.length === 0) {
417
- logger.throwArgumentError("missing providers", "providers", providers);
501
+ logger.throwArgumentError(
502
+ "missing providers",
503
+ "providers",
504
+ providers,
505
+ );
418
506
  }
419
507
 
420
- const providerConfigs: Array<FallbackProviderConfig> = providers.map((configOrProvider, index) => {
421
- if (Provider.isProvider(configOrProvider)) {
422
- const stallTimeout = isCommunityResource(configOrProvider) ? 2000: 750;
423
- const priority = 1;
424
- return Object.freeze({ provider: configOrProvider, weight: 1, stallTimeout, priority });
425
- }
508
+ const providerConfigs: Array<FallbackProviderConfig> = providers.map(
509
+ (configOrProvider, index) => {
510
+ if (Provider.isProvider(configOrProvider)) {
511
+ const stallTimeout = isCommunityResource(configOrProvider)
512
+ ? 2000
513
+ : 750;
514
+ const priority = 1;
515
+ return Object.freeze({
516
+ provider: configOrProvider,
517
+ weight: 1,
518
+ stallTimeout,
519
+ priority,
520
+ });
521
+ }
426
522
 
427
- const config: FallbackProviderConfig = shallowCopy(configOrProvider);
523
+ const config: FallbackProviderConfig =
524
+ shallowCopy(configOrProvider);
428
525
 
429
- if (config.priority == null) { config.priority = 1; }
430
- if (config.stallTimeout == null) {
431
- config.stallTimeout = isCommunityResource(configOrProvider) ? 2000: 750;
432
- }
433
- if (config.weight == null) { config.weight = 1; }
526
+ if (config.priority == null) {
527
+ config.priority = 1;
528
+ }
529
+ if (config.stallTimeout == null) {
530
+ config.stallTimeout = isCommunityResource(configOrProvider)
531
+ ? 2000
532
+ : 750;
533
+ }
534
+ if (config.weight == null) {
535
+ config.weight = 1;
536
+ }
434
537
 
435
- const weight = config.weight;
436
- if (weight % 1 || weight > 512 || weight < 1) {
437
- logger.throwArgumentError("invalid weight; must be integer in [1, 512]", `providers[${ index }].weight`, weight);
438
- }
538
+ const weight = config.weight;
539
+ if (weight % 1 || weight > 512 || weight < 1) {
540
+ logger.throwArgumentError(
541
+ "invalid weight; must be integer in [1, 512]",
542
+ `providers[${index}].weight`,
543
+ weight,
544
+ );
545
+ }
439
546
 
440
- return Object.freeze(config);
441
- });
547
+ return Object.freeze(config);
548
+ },
549
+ );
442
550
 
443
- const total = providerConfigs.reduce((accum, c) => (accum + c.weight), 0);
551
+ const total = providerConfigs.reduce((accum, c) => accum + c.weight, 0);
444
552
 
445
553
  if (quorum == null) {
446
554
  quorum = total / 2;
447
555
  } else if (quorum > total) {
448
- logger.throwArgumentError("quorum will always fail; larger than total weight", "quorum", quorum);
556
+ logger.throwArgumentError(
557
+ "quorum will always fail; larger than total weight",
558
+ "quorum",
559
+ quorum,
560
+ );
449
561
  }
450
562
 
451
563
  // Are all providers' networks are known
452
- let networkOrReady: Network | Promise<Network> = checkNetworks(providerConfigs.map((c) => (<any>(c.provider)).network));
564
+ let networkOrReady: Network | Promise<Network> = checkNetworks(
565
+ providerConfigs.map((c) => (<any>c.provider).network),
566
+ );
453
567
 
454
568
  // Not all networks are known; we must stall
455
569
  if (networkOrReady == null) {
@@ -470,25 +584,39 @@ export class FallbackProvider extends BaseProvider {
470
584
  }
471
585
 
472
586
  async detectNetwork(): Promise<Network> {
473
- const networks = await Promise.all(this.providerConfigs.map((c) => c.provider.getNetwork()));
587
+ const networks = await Promise.all(
588
+ this.providerConfigs.map((c) => c.provider.getNetwork()),
589
+ );
474
590
  return checkNetworks(networks);
475
591
  }
476
592
 
477
- async perform(method: string, params: { [name: string]: any }): Promise<any> {
593
+ async perform(
594
+ method: string,
595
+ params: { [name: string]: any },
596
+ ): Promise<any> {
478
597
  // Sending transactions is special; always broadcast it to all backends
479
598
  if (method === "sendTransaction") {
480
- const results: Array<string | Error> = await Promise.all(this.providerConfigs.map((c) => {
481
- return c.provider.sendTransaction(params.signedTransaction).then((result) => {
482
- return result.hash;
483
- }, (error) => {
484
- return error;
485
- });
486
- }));
599
+ const results: Array<string | Error> = await Promise.all(
600
+ this.providerConfigs.map((c) => {
601
+ return c.provider
602
+ .sendTransaction(params.signedTransaction)
603
+ .then(
604
+ (result) => {
605
+ return result.hash;
606
+ },
607
+ (error) => {
608
+ return error;
609
+ },
610
+ );
611
+ }),
612
+ );
487
613
 
488
614
  // Any success is good enough (other errors are likely "already seen" errors
489
615
  for (let i = 0; i < results.length; i++) {
490
616
  const result = results[i];
491
- if (typeof(result) === "string") { return result; }
617
+ if (typeof result === "string") {
618
+ return result;
619
+ }
492
620
  }
493
621
 
494
622
  // They were all an error; pick the first error
@@ -505,8 +633,10 @@ export class FallbackProvider extends BaseProvider {
505
633
 
506
634
  // Shuffle the providers and then sort them by their priority; we
507
635
  // shallowCopy them since we will store the result in them too
508
- const configs: Array<RunningConfig> = shuffled(this.providerConfigs.map(shallowCopy));
509
- configs.sort((a, b) => (a.priority - b.priority));
636
+ const configs: Array<RunningConfig> = shuffled(
637
+ this.providerConfigs.map(shallowCopy),
638
+ );
639
+ configs.sort((a, b) => a.priority - b.priority);
510
640
 
511
641
  const currentBlockNumber = this._highestBlockNumber;
512
642
 
@@ -516,8 +646,9 @@ export class FallbackProvider extends BaseProvider {
516
646
  const t0 = now();
517
647
 
518
648
  // Compute the inflight weight (exclude anything past)
519
- let inflightWeight = configs.filter((c) => (c.runner && ((t0 - c.start) < c.stallTimeout)))
520
- .reduce((accum, c) => (accum + c.weight), 0);
649
+ let inflightWeight = configs
650
+ .filter((c) => c.runner && t0 - c.start < c.stallTimeout)
651
+ .reduce((accum, c) => accum + c.weight, 0);
521
652
 
522
653
  // Start running enough to meet quorum
523
654
  while (inflightWeight < this.quorum && i < configs.length) {
@@ -527,44 +658,59 @@ export class FallbackProvider extends BaseProvider {
527
658
 
528
659
  config.start = now();
529
660
  config.staller = stall(config.stallTimeout);
530
- config.staller.wait(() => { config.staller = null; });
531
-
532
- config.runner = getRunner(config, currentBlockNumber, method, params).then((result) => {
533
- config.done = true;
534
- config.result = result;
535
-
536
- if (this.listenerCount("debug")) {
537
- this.emit("debug", {
538
- action: "request",
539
- rid: rid,
540
- backend: exposeDebugConfig(config, now()),
541
- request: { method: method, params: deepCopy(params) },
542
- provider: this
543
- });
544
- }
545
-
546
- }, (error) => {
547
- config.done = true;
548
- config.error = error;
549
-
550
- if (this.listenerCount("debug")) {
551
- this.emit("debug", {
552
- action: "request",
553
- rid: rid,
554
- backend: exposeDebugConfig(config, now()),
555
- request: { method: method, params: deepCopy(params) },
556
- provider: this
557
- });
558
- }
661
+ config.staller.wait(() => {
662
+ config.staller = null;
559
663
  });
560
664
 
665
+ config.runner = getRunner(
666
+ config,
667
+ currentBlockNumber,
668
+ method,
669
+ params,
670
+ ).then(
671
+ (result) => {
672
+ config.done = true;
673
+ config.result = result;
674
+
675
+ if (this.listenerCount("debug")) {
676
+ this.emit("debug", {
677
+ action: "request",
678
+ rid: rid,
679
+ backend: exposeDebugConfig(config, now()),
680
+ request: {
681
+ method: method,
682
+ params: deepCopy(params),
683
+ },
684
+ provider: this,
685
+ });
686
+ }
687
+ },
688
+ (error) => {
689
+ config.done = true;
690
+ config.error = error;
691
+
692
+ if (this.listenerCount("debug")) {
693
+ this.emit("debug", {
694
+ action: "request",
695
+ rid: rid,
696
+ backend: exposeDebugConfig(config, now()),
697
+ request: {
698
+ method: method,
699
+ params: deepCopy(params),
700
+ },
701
+ provider: this,
702
+ });
703
+ }
704
+ },
705
+ );
706
+
561
707
  if (this.listenerCount("debug")) {
562
708
  this.emit("debug", {
563
709
  action: "request",
564
710
  rid: rid,
565
711
  backend: exposeDebugConfig(config, null),
566
712
  request: { method: method, params: deepCopy(params) },
567
- provider: this
713
+ provider: this,
568
714
  });
569
715
  }
570
716
 
@@ -572,60 +718,83 @@ export class FallbackProvider extends BaseProvider {
572
718
  }
573
719
 
574
720
  // Wait for anything meaningful to finish or stall out
575
- const waiting: Array<Promise<any>> = [ ];
721
+ const waiting: Array<Promise<any>> = [];
576
722
  configs.forEach((c) => {
577
- if (c.done || !c.runner) { return; }
723
+ if (c.done || !c.runner) {
724
+ return;
725
+ }
578
726
  waiting.push(c.runner);
579
- if (c.staller) { waiting.push(c.staller.getPromise()); }
727
+ if (c.staller) {
728
+ waiting.push(c.staller.getPromise());
729
+ }
580
730
  });
581
731
 
582
- if (waiting.length) { await Promise.race(waiting); }
732
+ if (waiting.length) {
733
+ await Promise.race(waiting);
734
+ }
583
735
 
584
736
  // Check the quorum and process the results; the process function
585
737
  // may additionally decide the quorum is not met
586
- const results = configs.filter((c) => (c.done && c.error == null));
738
+ const results = configs.filter((c) => c.done && c.error == null);
587
739
  if (results.length >= this.quorum) {
588
740
  const result = processFunc(results);
589
741
  if (result !== undefined) {
590
742
  // Shut down any stallers
591
- configs.forEach(c => {
592
- if (c.staller) { c.staller.cancel(); }
743
+ configs.forEach((c) => {
744
+ if (c.staller) {
745
+ c.staller.cancel();
746
+ }
593
747
  c.cancelled = true;
594
748
  });
595
749
  return result;
596
750
  }
597
- if (!first) { await stall(100).getPromise(); }
751
+ if (!first) {
752
+ await stall(100).getPromise();
753
+ }
598
754
  first = false;
599
755
  }
600
756
 
601
757
  // No result, check for errors that should be forwarded
602
- const errors = configs.reduce((accum, c) => {
603
- if (!c.done || c.error == null) { return accum; }
758
+ const errors = configs.reduce(
759
+ (accum, c) => {
760
+ if (!c.done || c.error == null) {
761
+ return accum;
762
+ }
604
763
 
605
- const code = (<any>(c.error)).code;
606
- if (ForwardErrors.indexOf(code) >= 0) {
607
- if (!accum[code]) { accum[code] = { error: c.error, weight: 0 }; }
608
- accum[code].weight += c.weight;
609
- }
764
+ const code = (<any>c.error).code;
765
+ if (ForwardErrors.indexOf(code) >= 0) {
766
+ if (!accum[code]) {
767
+ accum[code] = { error: c.error, weight: 0 };
768
+ }
769
+ accum[code].weight += c.weight;
770
+ }
610
771
 
611
- return accum;
612
- }, <{ [ code: string ]: { error: Error, weight: number } }>({ }));
772
+ return accum;
773
+ },
774
+ <{ [code: string]: { error: Error; weight: number } }>{},
775
+ );
613
776
 
614
777
  Object.keys(errors).forEach((errorCode: string) => {
615
778
  const tally = errors[errorCode];
616
- if (tally.weight < this.quorum) { return; }
779
+ if (tally.weight < this.quorum) {
780
+ return;
781
+ }
617
782
 
618
783
  // Shut down any stallers
619
- configs.forEach(c => {
620
- if (c.staller) { c.staller.cancel(); }
784
+ configs.forEach((c) => {
785
+ if (c.staller) {
786
+ c.staller.cancel();
787
+ }
621
788
  c.cancelled = true;
622
789
  });
623
790
 
624
- const e = <any>(tally.error);
791
+ const e = <any>tally.error;
625
792
 
626
- const props: { [ name: string ]: any } = { };
793
+ const props: { [name: string]: any } = {};
627
794
  ForwardProperties.forEach((name) => {
628
- if (e[name] == null) { return; }
795
+ if (e[name] == null) {
796
+ return;
797
+ }
629
798
  props[name] = e[name];
630
799
  });
631
800
 
@@ -633,22 +802,30 @@ export class FallbackProvider extends BaseProvider {
633
802
  });
634
803
 
635
804
  // All configs have run to completion; we will never get more data
636
- if (configs.filter((c) => !c.done).length === 0) { break; }
805
+ if (configs.filter((c) => !c.done).length === 0) {
806
+ break;
807
+ }
637
808
  }
638
809
 
639
810
  // Shut down any stallers; shouldn't be any
640
- configs.forEach(c => {
641
- if (c.staller) { c.staller.cancel(); }
811
+ configs.forEach((c) => {
812
+ if (c.staller) {
813
+ c.staller.cancel();
814
+ }
642
815
  c.cancelled = true;
643
816
  });
644
817
 
645
- return logger.throwError("failed to meet quorum", Logger.errors.SERVER_ERROR, {
646
- method: method,
647
- params: params,
648
- //results: configs.map((c) => c.result),
649
- //errors: configs.map((c) => c.error),
650
- results: configs.map((c) => exposeDebugConfig(c)),
651
- provider: this
652
- });
818
+ return logger.throwError(
819
+ "failed to meet quorum",
820
+ Logger.errors.SERVER_ERROR,
821
+ {
822
+ method: method,
823
+ params: params,
824
+ //results: configs.map((c) => c.result),
825
+ //errors: configs.map((c) => c.error),
826
+ results: configs.map((c) => exposeDebugConfig(c)),
827
+ provider: this,
828
+ },
829
+ );
653
830
  }
654
831
  }