UNPKG

34.9 kBJavaScriptView Raw
1"use strict";
2var __extends = (this && this.__extends) || (function () {
3 var extendStatics = function (d, b) {
4 extendStatics = Object.setPrototypeOf ||
5 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6 function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7 return extendStatics(d, b);
8 };
9 return function (d, b) {
10 if (typeof b !== "function" && b !== null)
11 throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12 extendStatics(d, b);
13 function __() { this.constructor = d; }
14 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15 };
16})();
17var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
19 return new (P || (P = Promise))(function (resolve, reject) {
20 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
21 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
22 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
23 step((generator = generator.apply(thisArg, _arguments || [])).next());
24 });
25};
26var __generator = (this && this.__generator) || function (thisArg, body) {
27 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
28 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
29 function verb(n) { return function (v) { return step([n, v]); }; }
30 function step(op) {
31 if (f) throw new TypeError("Generator is already executing.");
32 while (_) try {
33 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
34 if (y = 0, t) op = [op[0] & 2, t.value];
35 switch (op[0]) {
36 case 0: case 1: t = op; break;
37 case 4: _.label++; return { value: op[1], done: false };
38 case 5: _.label++; y = op[1]; op = [0]; continue;
39 case 7: op = _.ops.pop(); _.trys.pop(); continue;
40 default:
41 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
42 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
43 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
44 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
45 if (t[2]) _.ops.pop();
46 _.trys.pop(); continue;
47 }
48 op = body.call(thisArg, _);
49 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
50 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
51 }
52};
53Object.defineProperty(exports, "__esModule", { value: true });
54exports.FallbackProvider = void 0;
55var abstract_provider_1 = require("@ethersproject/abstract-provider");
56var bignumber_1 = require("@ethersproject/bignumber");
57var bytes_1 = require("@ethersproject/bytes");
58var properties_1 = require("@ethersproject/properties");
59var random_1 = require("@ethersproject/random");
60var web_1 = require("@ethersproject/web");
61var base_provider_1 = require("./base-provider");
62var formatter_1 = require("./formatter");
63var logger_1 = require("@ethersproject/logger");
64var _version_1 = require("./_version");
65var logger = new logger_1.Logger(_version_1.version);
66function now() { return (new Date()).getTime(); }
67// Returns to network as long as all agree, or null if any is null.
68// Throws an error if any two networks do not match.
69function checkNetworks(networks) {
70 var result = null;
71 for (var i = 0; i < networks.length; i++) {
72 var network = networks[i];
73 // Null! We do not know our network; bail.
74 if (network == null) {
75 return null;
76 }
77 if (result) {
78 // Make sure the network matches the previous networks
79 if (!(result.name === network.name && result.chainId === network.chainId &&
80 ((result.ensAddress === network.ensAddress) || (result.ensAddress == null && network.ensAddress == null)))) {
81 logger.throwArgumentError("provider mismatch", "networks", networks);
82 }
83 }
84 else {
85 result = network;
86 }
87 }
88 return result;
89}
90function median(values, maxDelta) {
91 values = values.slice().sort();
92 var middle = Math.floor(values.length / 2);
93 // Odd length; take the middle
94 if (values.length % 2) {
95 return values[middle];
96 }
97 // Even length; take the average of the two middle
98 var a = values[middle - 1], b = values[middle];
99 if (maxDelta != null && Math.abs(a - b) > maxDelta) {
100 return null;
101 }
102 return (a + b) / 2;
103}
104function serialize(value) {
105 if (value === null) {
106 return "null";
107 }
108 else if (typeof (value) === "number" || typeof (value) === "boolean") {
109 return JSON.stringify(value);
110 }
111 else if (typeof (value) === "string") {
112 return value;
113 }
114 else if (bignumber_1.BigNumber.isBigNumber(value)) {
115 return value.toString();
116 }
117 else if (Array.isArray(value)) {
118 return JSON.stringify(value.map(function (i) { return serialize(i); }));
119 }
120 else if (typeof (value) === "object") {
121 var keys = Object.keys(value);
122 keys.sort();
123 return "{" + keys.map(function (key) {
124 var v = value[key];
125 if (typeof (v) === "function") {
126 v = "[function]";
127 }
128 else {
129 v = serialize(v);
130 }
131 return JSON.stringify(key) + ":" + v;
132 }).join(",") + "}";
133 }
134 throw new Error("unknown value type: " + typeof (value));
135}
136// Next request ID to use for emitting debug info
137var nextRid = 1;
138;
139function stall(duration) {
140 var cancel = null;
141 var timer = null;
142 var promise = (new Promise(function (resolve) {
143 cancel = function () {
144 if (timer) {
145 clearTimeout(timer);
146 timer = null;
147 }
148 resolve();
149 };
150 timer = setTimeout(cancel, duration);
151 }));
152 var wait = function (func) {
153 promise = promise.then(func);
154 return promise;
155 };
156 function getPromise() {
157 return promise;
158 }
159 return { cancel: cancel, getPromise: getPromise, wait: wait };
160}
161var ForwardErrors = [
162 logger_1.Logger.errors.CALL_EXCEPTION,
163 logger_1.Logger.errors.INSUFFICIENT_FUNDS,
164 logger_1.Logger.errors.NONCE_EXPIRED,
165 logger_1.Logger.errors.REPLACEMENT_UNDERPRICED,
166 logger_1.Logger.errors.UNPREDICTABLE_GAS_LIMIT
167];
168var ForwardProperties = [
169 "address",
170 "args",
171 "errorArgs",
172 "errorSignature",
173 "method",
174 "transaction",
175];
176;
177function exposeDebugConfig(config, now) {
178 var result = {
179 weight: config.weight
180 };
181 Object.defineProperty(result, "provider", { get: function () { return config.provider; } });
182 if (config.start) {
183 result.start = config.start;
184 }
185 if (now) {
186 result.duration = (now - config.start);
187 }
188 if (config.done) {
189 if (config.error) {
190 result.error = config.error;
191 }
192 else {
193 result.result = config.result || null;
194 }
195 }
196 return result;
197}
198function normalizedTally(normalize, quorum) {
199 return function (configs) {
200 // Count the votes for each result
201 var tally = {};
202 configs.forEach(function (c) {
203 var value = normalize(c.result);
204 if (!tally[value]) {
205 tally[value] = { count: 0, result: c.result };
206 }
207 tally[value].count++;
208 });
209 // Check for a quorum on any given result
210 var keys = Object.keys(tally);
211 for (var i = 0; i < keys.length; i++) {
212 var check = tally[keys[i]];
213 if (check.count >= quorum) {
214 return check.result;
215 }
216 }
217 // No quroum
218 return undefined;
219 };
220}
221function getProcessFunc(provider, method, params) {
222 var normalize = serialize;
223 switch (method) {
224 case "getBlockNumber":
225 // Return the median value, unless there is (median + 1) is also
226 // present, in which case that is probably true and the median
227 // is going to be stale soon. In the event of a malicious node,
228 // the lie will be true soon enough.
229 return function (configs) {
230 var values = configs.map(function (c) { return c.result; });
231 // Get the median block number
232 var blockNumber = median(configs.map(function (c) { return c.result; }), 2);
233 if (blockNumber == null) {
234 return undefined;
235 }
236 blockNumber = Math.ceil(blockNumber);
237 // If the next block height is present, its prolly safe to use
238 if (values.indexOf(blockNumber + 1) >= 0) {
239 blockNumber++;
240 }
241 // Don't ever roll back the blockNumber
242 if (blockNumber >= provider._highestBlockNumber) {
243 provider._highestBlockNumber = blockNumber;
244 }
245 return provider._highestBlockNumber;
246 };
247 case "getGasPrice":
248 // Return the middle (round index up) value, similar to median
249 // but do not average even entries and choose the higher.
250 // Malicious actors must compromise 50% of the nodes to lie.
251 return function (configs) {
252 var values = configs.map(function (c) { return c.result; });
253 values.sort();
254 return values[Math.floor(values.length / 2)];
255 };
256 case "getEtherPrice":
257 // Returns the median price. Malicious actors must compromise at
258 // least 50% of the nodes to lie (in a meaningful way).
259 return function (configs) {
260 return median(configs.map(function (c) { return c.result; }));
261 };
262 // No additional normalizing required; serialize is enough
263 case "getBalance":
264 case "getTransactionCount":
265 case "getCode":
266 case "getStorageAt":
267 case "call":
268 case "estimateGas":
269 case "getLogs":
270 break;
271 // We drop the confirmations from transactions as it is approximate
272 case "getTransaction":
273 case "getTransactionReceipt":
274 normalize = function (tx) {
275 if (tx == null) {
276 return null;
277 }
278 tx = (0, properties_1.shallowCopy)(tx);
279 tx.confirmations = -1;
280 return serialize(tx);
281 };
282 break;
283 // We drop the confirmations from transactions as it is approximate
284 case "getBlock":
285 // We drop the confirmations from transactions as it is approximate
286 if (params.includeTransactions) {
287 normalize = function (block) {
288 if (block == null) {
289 return null;
290 }
291 block = (0, properties_1.shallowCopy)(block);
292 block.transactions = block.transactions.map(function (tx) {
293 tx = (0, properties_1.shallowCopy)(tx);
294 tx.confirmations = -1;
295 return tx;
296 });
297 return serialize(block);
298 };
299 }
300 else {
301 normalize = function (block) {
302 if (block == null) {
303 return null;
304 }
305 return serialize(block);
306 };
307 }
308 break;
309 default:
310 throw new Error("unknown method: " + method);
311 }
312 // Return the result if and only if the expected quorum is
313 // satisfied and agreed upon for the final result.
314 return normalizedTally(normalize, provider.quorum);
315}
316// If we are doing a blockTag query, we need to make sure the backend is
317// caught up to the FallbackProvider, before sending a request to it.
318function waitForSync(config, blockNumber) {
319 return __awaiter(this, void 0, void 0, function () {
320 var provider;
321 return __generator(this, function (_a) {
322 provider = (config.provider);
323 if ((provider.blockNumber != null && provider.blockNumber >= blockNumber) || blockNumber === -1) {
324 return [2 /*return*/, provider];
325 }
326 return [2 /*return*/, (0, web_1.poll)(function () {
327 return new Promise(function (resolve, reject) {
328 setTimeout(function () {
329 // We are synced
330 if (provider.blockNumber >= blockNumber) {
331 return resolve(provider);
332 }
333 // We're done; just quit
334 if (config.cancelled) {
335 return resolve(null);
336 }
337 // Try again, next block
338 return resolve(undefined);
339 }, 0);
340 });
341 }, { oncePoll: provider })];
342 });
343 });
344}
345function getRunner(config, currentBlockNumber, method, params) {
346 return __awaiter(this, void 0, void 0, function () {
347 var provider, _a, filter;
348 return __generator(this, function (_b) {
349 switch (_b.label) {
350 case 0:
351 provider = config.provider;
352 _a = method;
353 switch (_a) {
354 case "getBlockNumber": return [3 /*break*/, 1];
355 case "getGasPrice": return [3 /*break*/, 1];
356 case "getEtherPrice": return [3 /*break*/, 2];
357 case "getBalance": return [3 /*break*/, 3];
358 case "getTransactionCount": return [3 /*break*/, 3];
359 case "getCode": return [3 /*break*/, 3];
360 case "getStorageAt": return [3 /*break*/, 6];
361 case "getBlock": return [3 /*break*/, 9];
362 case "call": return [3 /*break*/, 12];
363 case "estimateGas": return [3 /*break*/, 12];
364 case "getTransaction": return [3 /*break*/, 15];
365 case "getTransactionReceipt": return [3 /*break*/, 15];
366 case "getLogs": return [3 /*break*/, 16];
367 }
368 return [3 /*break*/, 19];
369 case 1: return [2 /*return*/, provider[method]()];
370 case 2:
371 if (provider.getEtherPrice) {
372 return [2 /*return*/, provider.getEtherPrice()];
373 }
374 return [3 /*break*/, 19];
375 case 3:
376 if (!(params.blockTag && (0, bytes_1.isHexString)(params.blockTag))) return [3 /*break*/, 5];
377 return [4 /*yield*/, waitForSync(config, currentBlockNumber)];
378 case 4:
379 provider = _b.sent();
380 _b.label = 5;
381 case 5: return [2 /*return*/, provider[method](params.address, params.blockTag || "latest")];
382 case 6:
383 if (!(params.blockTag && (0, bytes_1.isHexString)(params.blockTag))) return [3 /*break*/, 8];
384 return [4 /*yield*/, waitForSync(config, currentBlockNumber)];
385 case 7:
386 provider = _b.sent();
387 _b.label = 8;
388 case 8: return [2 /*return*/, provider.getStorageAt(params.address, params.position, params.blockTag || "latest")];
389 case 9:
390 if (!(params.blockTag && (0, bytes_1.isHexString)(params.blockTag))) return [3 /*break*/, 11];
391 return [4 /*yield*/, waitForSync(config, currentBlockNumber)];
392 case 10:
393 provider = _b.sent();
394 _b.label = 11;
395 case 11: return [2 /*return*/, provider[(params.includeTransactions ? "getBlockWithTransactions" : "getBlock")](params.blockTag || params.blockHash)];
396 case 12:
397 if (!(params.blockTag && (0, bytes_1.isHexString)(params.blockTag))) return [3 /*break*/, 14];
398 return [4 /*yield*/, waitForSync(config, currentBlockNumber)];
399 case 13:
400 provider = _b.sent();
401 _b.label = 14;
402 case 14:
403 if (method === "call" && params.blockTag) {
404 return [2 /*return*/, provider[method](params.transaction, params.blockTag)];
405 }
406 return [2 /*return*/, provider[method](params.transaction)];
407 case 15: return [2 /*return*/, provider[method](params.transactionHash)];
408 case 16:
409 filter = params.filter;
410 if (!((filter.fromBlock && (0, bytes_1.isHexString)(filter.fromBlock)) || (filter.toBlock && (0, bytes_1.isHexString)(filter.toBlock)))) return [3 /*break*/, 18];
411 return [4 /*yield*/, waitForSync(config, currentBlockNumber)];
412 case 17:
413 provider = _b.sent();
414 _b.label = 18;
415 case 18: return [2 /*return*/, provider.getLogs(filter)];
416 case 19: return [2 /*return*/, logger.throwError("unknown method error", logger_1.Logger.errors.UNKNOWN_ERROR, {
417 method: method,
418 params: params
419 })];
420 }
421 });
422 });
423}
424var FallbackProvider = /** @class */ (function (_super) {
425 __extends(FallbackProvider, _super);
426 function FallbackProvider(providers, quorum) {
427 var _this = this;
428 if (providers.length === 0) {
429 logger.throwArgumentError("missing providers", "providers", providers);
430 }
431 var providerConfigs = providers.map(function (configOrProvider, index) {
432 if (abstract_provider_1.Provider.isProvider(configOrProvider)) {
433 var stallTimeout = (0, formatter_1.isCommunityResource)(configOrProvider) ? 2000 : 750;
434 var priority = 1;
435 return Object.freeze({ provider: configOrProvider, weight: 1, stallTimeout: stallTimeout, priority: priority });
436 }
437 var config = (0, properties_1.shallowCopy)(configOrProvider);
438 if (config.priority == null) {
439 config.priority = 1;
440 }
441 if (config.stallTimeout == null) {
442 config.stallTimeout = (0, formatter_1.isCommunityResource)(configOrProvider) ? 2000 : 750;
443 }
444 if (config.weight == null) {
445 config.weight = 1;
446 }
447 var weight = config.weight;
448 if (weight % 1 || weight > 512 || weight < 1) {
449 logger.throwArgumentError("invalid weight; must be integer in [1, 512]", "providers[" + index + "].weight", weight);
450 }
451 return Object.freeze(config);
452 });
453 var total = providerConfigs.reduce(function (accum, c) { return (accum + c.weight); }, 0);
454 if (quorum == null) {
455 quorum = total / 2;
456 }
457 else if (quorum > total) {
458 logger.throwArgumentError("quorum will always fail; larger than total weight", "quorum", quorum);
459 }
460 // Are all providers' networks are known
461 var networkOrReady = checkNetworks(providerConfigs.map(function (c) { return (c.provider).network; }));
462 // Not all networks are known; we must stall
463 if (networkOrReady == null) {
464 networkOrReady = new Promise(function (resolve, reject) {
465 setTimeout(function () {
466 _this.detectNetwork().then(resolve, reject);
467 }, 0);
468 });
469 }
470 _this = _super.call(this, networkOrReady) || this;
471 // Preserve a copy, so we do not get mutated
472 (0, properties_1.defineReadOnly)(_this, "providerConfigs", Object.freeze(providerConfigs));
473 (0, properties_1.defineReadOnly)(_this, "quorum", quorum);
474 _this._highestBlockNumber = -1;
475 return _this;
476 }
477 FallbackProvider.prototype.detectNetwork = function () {
478 return __awaiter(this, void 0, void 0, function () {
479 var networks;
480 return __generator(this, function (_a) {
481 switch (_a.label) {
482 case 0: return [4 /*yield*/, Promise.all(this.providerConfigs.map(function (c) { return c.provider.getNetwork(); }))];
483 case 1:
484 networks = _a.sent();
485 return [2 /*return*/, checkNetworks(networks)];
486 }
487 });
488 });
489 };
490 FallbackProvider.prototype.perform = function (method, params) {
491 return __awaiter(this, void 0, void 0, function () {
492 var results, i_1, result, processFunc, configs, currentBlockNumber, i, first, _loop_1, this_1, state_1;
493 var _this = this;
494 return __generator(this, function (_a) {
495 switch (_a.label) {
496 case 0:
497 if (!(method === "sendTransaction")) return [3 /*break*/, 2];
498 return [4 /*yield*/, Promise.all(this.providerConfigs.map(function (c) {
499 return c.provider.sendTransaction(params.signedTransaction).then(function (result) {
500 return result.hash;
501 }, function (error) {
502 return error;
503 });
504 }))];
505 case 1:
506 results = _a.sent();
507 // Any success is good enough (other errors are likely "already seen" errors
508 for (i_1 = 0; i_1 < results.length; i_1++) {
509 result = results[i_1];
510 if (typeof (result) === "string") {
511 return [2 /*return*/, result];
512 }
513 }
514 // They were all an error; pick the first error
515 throw results[0];
516 case 2:
517 if (!(this._highestBlockNumber === -1 && method !== "getBlockNumber")) return [3 /*break*/, 4];
518 return [4 /*yield*/, this.getBlockNumber()];
519 case 3:
520 _a.sent();
521 _a.label = 4;
522 case 4:
523 processFunc = getProcessFunc(this, method, params);
524 configs = (0, random_1.shuffled)(this.providerConfigs.map(properties_1.shallowCopy));
525 configs.sort(function (a, b) { return (a.priority - b.priority); });
526 currentBlockNumber = this._highestBlockNumber;
527 i = 0;
528 first = true;
529 _loop_1 = function () {
530 var t0, inflightWeight, _loop_2, waiting, results, result, errors;
531 return __generator(this, function (_b) {
532 switch (_b.label) {
533 case 0:
534 t0 = now();
535 inflightWeight = configs.filter(function (c) { return (c.runner && ((t0 - c.start) < c.stallTimeout)); })
536 .reduce(function (accum, c) { return (accum + c.weight); }, 0);
537 _loop_2 = function () {
538 var config = configs[i++];
539 var rid = nextRid++;
540 config.start = now();
541 config.staller = stall(config.stallTimeout);
542 config.staller.wait(function () { config.staller = null; });
543 config.runner = getRunner(config, currentBlockNumber, method, params).then(function (result) {
544 config.done = true;
545 config.result = result;
546 if (_this.listenerCount("debug")) {
547 _this.emit("debug", {
548 action: "request",
549 rid: rid,
550 backend: exposeDebugConfig(config, now()),
551 request: { method: method, params: (0, properties_1.deepCopy)(params) },
552 provider: _this
553 });
554 }
555 }, function (error) {
556 config.done = true;
557 config.error = error;
558 if (_this.listenerCount("debug")) {
559 _this.emit("debug", {
560 action: "request",
561 rid: rid,
562 backend: exposeDebugConfig(config, now()),
563 request: { method: method, params: (0, properties_1.deepCopy)(params) },
564 provider: _this
565 });
566 }
567 });
568 if (this_1.listenerCount("debug")) {
569 this_1.emit("debug", {
570 action: "request",
571 rid: rid,
572 backend: exposeDebugConfig(config, null),
573 request: { method: method, params: (0, properties_1.deepCopy)(params) },
574 provider: this_1
575 });
576 }
577 inflightWeight += config.weight;
578 };
579 // Start running enough to meet quorum
580 while (inflightWeight < this_1.quorum && i < configs.length) {
581 _loop_2();
582 }
583 waiting = [];
584 configs.forEach(function (c) {
585 if (c.done || !c.runner) {
586 return;
587 }
588 waiting.push(c.runner);
589 if (c.staller) {
590 waiting.push(c.staller.getPromise());
591 }
592 });
593 if (!waiting.length) return [3 /*break*/, 2];
594 return [4 /*yield*/, Promise.race(waiting)];
595 case 1:
596 _b.sent();
597 _b.label = 2;
598 case 2:
599 results = configs.filter(function (c) { return (c.done && c.error == null); });
600 if (!(results.length >= this_1.quorum)) return [3 /*break*/, 5];
601 result = processFunc(results);
602 if (result !== undefined) {
603 // Shut down any stallers
604 configs.forEach(function (c) {
605 if (c.staller) {
606 c.staller.cancel();
607 }
608 c.cancelled = true;
609 });
610 return [2 /*return*/, { value: result }];
611 }
612 if (!!first) return [3 /*break*/, 4];
613 return [4 /*yield*/, stall(100).getPromise()];
614 case 3:
615 _b.sent();
616 _b.label = 4;
617 case 4:
618 first = false;
619 _b.label = 5;
620 case 5:
621 errors = configs.reduce(function (accum, c) {
622 if (!c.done || c.error == null) {
623 return accum;
624 }
625 var code = (c.error).code;
626 if (ForwardErrors.indexOf(code) >= 0) {
627 if (!accum[code]) {
628 accum[code] = { error: c.error, weight: 0 };
629 }
630 accum[code].weight += c.weight;
631 }
632 return accum;
633 }, ({}));
634 Object.keys(errors).forEach(function (errorCode) {
635 var tally = errors[errorCode];
636 if (tally.weight < _this.quorum) {
637 return;
638 }
639 // Shut down any stallers
640 configs.forEach(function (c) {
641 if (c.staller) {
642 c.staller.cancel();
643 }
644 c.cancelled = true;
645 });
646 var e = (tally.error);
647 var props = {};
648 ForwardProperties.forEach(function (name) {
649 if (e[name] == null) {
650 return;
651 }
652 props[name] = e[name];
653 });
654 logger.throwError(e.reason || e.message, errorCode, props);
655 });
656 // All configs have run to completion; we will never get more data
657 if (configs.filter(function (c) { return !c.done; }).length === 0) {
658 return [2 /*return*/, "break"];
659 }
660 return [2 /*return*/];
661 }
662 });
663 };
664 this_1 = this;
665 _a.label = 5;
666 case 5:
667 if (!true) return [3 /*break*/, 7];
668 return [5 /*yield**/, _loop_1()];
669 case 6:
670 state_1 = _a.sent();
671 if (typeof state_1 === "object")
672 return [2 /*return*/, state_1.value];
673 if (state_1 === "break")
674 return [3 /*break*/, 7];
675 return [3 /*break*/, 5];
676 case 7:
677 // Shut down any stallers; shouldn't be any
678 configs.forEach(function (c) {
679 if (c.staller) {
680 c.staller.cancel();
681 }
682 c.cancelled = true;
683 });
684 return [2 /*return*/, logger.throwError("failed to meet quorum", logger_1.Logger.errors.SERVER_ERROR, {
685 method: method,
686 params: params,
687 //results: configs.map((c) => c.result),
688 //errors: configs.map((c) => c.error),
689 results: configs.map(function (c) { return exposeDebugConfig(c); }),
690 provider: this
691 })];
692 }
693 });
694 });
695 };
696 return FallbackProvider;
697}(base_provider_1.BaseProvider));
698exports.FallbackProvider = FallbackProvider;
699//# sourceMappingURL=fallback-provider.js.map
\No newline at end of file