1 | "use strict";
|
2 | var __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 | })();
|
17 | var __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 | };
|
26 | var __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 | };
|
53 | Object.defineProperty(exports, "__esModule", { value: true });
|
54 | exports.FallbackProvider = void 0;
|
55 | var abstract_provider_1 = require("@ethersproject/abstract-provider");
|
56 | var bignumber_1 = require("@ethersproject/bignumber");
|
57 | var bytes_1 = require("@ethersproject/bytes");
|
58 | var properties_1 = require("@ethersproject/properties");
|
59 | var random_1 = require("@ethersproject/random");
|
60 | var web_1 = require("@ethersproject/web");
|
61 | var base_provider_1 = require("./base-provider");
|
62 | var formatter_1 = require("./formatter");
|
63 | var logger_1 = require("@ethersproject/logger");
|
64 | var _version_1 = require("./_version");
|
65 | var logger = new logger_1.Logger(_version_1.version);
|
66 | function now() { return (new Date()).getTime(); }
|
67 |
|
68 |
|
69 | function checkNetworks(networks) {
|
70 | var result = null;
|
71 | for (var i = 0; i < networks.length; i++) {
|
72 | var network = networks[i];
|
73 |
|
74 | if (network == null) {
|
75 | return null;
|
76 | }
|
77 | if (result) {
|
78 |
|
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 | }
|
90 | function median(values, maxDelta) {
|
91 | values = values.slice().sort();
|
92 | var middle = Math.floor(values.length / 2);
|
93 |
|
94 | if (values.length % 2) {
|
95 | return values[middle];
|
96 | }
|
97 |
|
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 | }
|
104 | function 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 |
|
137 | var nextRid = 1;
|
138 | ;
|
139 | function 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 | }
|
161 | var 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 | ];
|
168 | var ForwardProperties = [
|
169 | "address",
|
170 | "args",
|
171 | "errorArgs",
|
172 | "errorSignature",
|
173 | "method",
|
174 | "transaction",
|
175 | ];
|
176 | ;
|
177 | function 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 | }
|
198 | function normalizedTally(normalize, quorum) {
|
199 | return function (configs) {
|
200 |
|
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 |
|
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 |
|
218 | return undefined;
|
219 | };
|
220 | }
|
221 | function getProcessFunc(provider, method, params) {
|
222 | var normalize = serialize;
|
223 | switch (method) {
|
224 | case "getBlockNumber":
|
225 |
|
226 |
|
227 |
|
228 |
|
229 | return function (configs) {
|
230 | var values = configs.map(function (c) { return c.result; });
|
231 |
|
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 |
|
238 | if (values.indexOf(blockNumber + 1) >= 0) {
|
239 | blockNumber++;
|
240 | }
|
241 |
|
242 | if (blockNumber >= provider._highestBlockNumber) {
|
243 | provider._highestBlockNumber = blockNumber;
|
244 | }
|
245 | return provider._highestBlockNumber;
|
246 | };
|
247 | case "getGasPrice":
|
248 |
|
249 |
|
250 |
|
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 |
|
258 |
|
259 | return function (configs) {
|
260 | return median(configs.map(function (c) { return c.result; }));
|
261 | };
|
262 |
|
263 | case "getBalance":
|
264 | case "getTransactionCount":
|
265 | case "getCode":
|
266 | case "getStorageAt":
|
267 | case "call":
|
268 | case "estimateGas":
|
269 | case "getLogs":
|
270 | break;
|
271 |
|
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 |
|
284 | case "getBlock":
|
285 |
|
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 |
|
313 |
|
314 | return normalizedTally(normalize, provider.quorum);
|
315 | }
|
316 |
|
317 |
|
318 | function 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 , provider];
|
325 | }
|
326 | return [2 , (0, web_1.poll)(function () {
|
327 | return new Promise(function (resolve, reject) {
|
328 | setTimeout(function () {
|
329 |
|
330 | if (provider.blockNumber >= blockNumber) {
|
331 | return resolve(provider);
|
332 | }
|
333 |
|
334 | if (config.cancelled) {
|
335 | return resolve(null);
|
336 | }
|
337 |
|
338 | return resolve(undefined);
|
339 | }, 0);
|
340 | });
|
341 | }, { oncePoll: provider })];
|
342 | });
|
343 | });
|
344 | }
|
345 | function 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 , 1];
|
355 | case "getGasPrice": return [3 , 1];
|
356 | case "getEtherPrice": return [3 , 2];
|
357 | case "getBalance": return [3 , 3];
|
358 | case "getTransactionCount": return [3 , 3];
|
359 | case "getCode": return [3 , 3];
|
360 | case "getStorageAt": return [3 , 6];
|
361 | case "getBlock": return [3 , 9];
|
362 | case "call": return [3 , 12];
|
363 | case "estimateGas": return [3 , 12];
|
364 | case "getTransaction": return [3 , 15];
|
365 | case "getTransactionReceipt": return [3 , 15];
|
366 | case "getLogs": return [3 , 16];
|
367 | }
|
368 | return [3 , 19];
|
369 | case 1: return [2 , provider[method]()];
|
370 | case 2:
|
371 | if (provider.getEtherPrice) {
|
372 | return [2 , provider.getEtherPrice()];
|
373 | }
|
374 | return [3 , 19];
|
375 | case 3:
|
376 | if (!(params.blockTag && (0, bytes_1.isHexString)(params.blockTag))) return [3 , 5];
|
377 | return [4 , waitForSync(config, currentBlockNumber)];
|
378 | case 4:
|
379 | provider = _b.sent();
|
380 | _b.label = 5;
|
381 | case 5: return [2 , provider[method](params.address, params.blockTag || "latest")];
|
382 | case 6:
|
383 | if (!(params.blockTag && (0, bytes_1.isHexString)(params.blockTag))) return [3 , 8];
|
384 | return [4 , waitForSync(config, currentBlockNumber)];
|
385 | case 7:
|
386 | provider = _b.sent();
|
387 | _b.label = 8;
|
388 | case 8: return [2 , provider.getStorageAt(params.address, params.position, params.blockTag || "latest")];
|
389 | case 9:
|
390 | if (!(params.blockTag && (0, bytes_1.isHexString)(params.blockTag))) return [3 , 11];
|
391 | return [4 , waitForSync(config, currentBlockNumber)];
|
392 | case 10:
|
393 | provider = _b.sent();
|
394 | _b.label = 11;
|
395 | case 11: return [2 , provider[(params.includeTransactions ? "getBlockWithTransactions" : "getBlock")](params.blockTag || params.blockHash)];
|
396 | case 12:
|
397 | if (!(params.blockTag && (0, bytes_1.isHexString)(params.blockTag))) return [3 , 14];
|
398 | return [4 , waitForSync(config, currentBlockNumber)];
|
399 | case 13:
|
400 | provider = _b.sent();
|
401 | _b.label = 14;
|
402 | case 14: return [2 , provider[method](params.transaction)];
|
403 | case 15: return [2 , provider[method](params.transactionHash)];
|
404 | case 16:
|
405 | filter = params.filter;
|
406 | if (!((filter.fromBlock && (0, bytes_1.isHexString)(filter.fromBlock)) || (filter.toBlock && (0, bytes_1.isHexString)(filter.toBlock)))) return [3 , 18];
|
407 | return [4 , waitForSync(config, currentBlockNumber)];
|
408 | case 17:
|
409 | provider = _b.sent();
|
410 | _b.label = 18;
|
411 | case 18: return [2 , provider.getLogs(filter)];
|
412 | case 19: return [2 , logger.throwError("unknown method error", logger_1.Logger.errors.UNKNOWN_ERROR, {
|
413 | method: method,
|
414 | params: params
|
415 | })];
|
416 | }
|
417 | });
|
418 | });
|
419 | }
|
420 | var FallbackProvider = (function (_super) {
|
421 | __extends(FallbackProvider, _super);
|
422 | function FallbackProvider(providers, quorum) {
|
423 | var _this = this;
|
424 | if (providers.length === 0) {
|
425 | logger.throwArgumentError("missing providers", "providers", providers);
|
426 | }
|
427 | var providerConfigs = providers.map(function (configOrProvider, index) {
|
428 | if (abstract_provider_1.Provider.isProvider(configOrProvider)) {
|
429 | var stallTimeout = (0, formatter_1.isCommunityResource)(configOrProvider) ? 2000 : 750;
|
430 | var priority = 1;
|
431 | return Object.freeze({ provider: configOrProvider, weight: 1, stallTimeout: stallTimeout, priority: priority });
|
432 | }
|
433 | var config = (0, properties_1.shallowCopy)(configOrProvider);
|
434 | if (config.priority == null) {
|
435 | config.priority = 1;
|
436 | }
|
437 | if (config.stallTimeout == null) {
|
438 | config.stallTimeout = (0, formatter_1.isCommunityResource)(configOrProvider) ? 2000 : 750;
|
439 | }
|
440 | if (config.weight == null) {
|
441 | config.weight = 1;
|
442 | }
|
443 | var weight = config.weight;
|
444 | if (weight % 1 || weight > 512 || weight < 1) {
|
445 | logger.throwArgumentError("invalid weight; must be integer in [1, 512]", "providers[" + index + "].weight", weight);
|
446 | }
|
447 | return Object.freeze(config);
|
448 | });
|
449 | var total = providerConfigs.reduce(function (accum, c) { return (accum + c.weight); }, 0);
|
450 | if (quorum == null) {
|
451 | quorum = total / 2;
|
452 | }
|
453 | else if (quorum > total) {
|
454 | logger.throwArgumentError("quorum will always fail; larger than total weight", "quorum", quorum);
|
455 | }
|
456 |
|
457 | var networkOrReady = checkNetworks(providerConfigs.map(function (c) { return (c.provider).network; }));
|
458 |
|
459 | if (networkOrReady == null) {
|
460 | networkOrReady = new Promise(function (resolve, reject) {
|
461 | setTimeout(function () {
|
462 | _this.detectNetwork().then(resolve, reject);
|
463 | }, 0);
|
464 | });
|
465 | }
|
466 | _this = _super.call(this, networkOrReady) || this;
|
467 |
|
468 | (0, properties_1.defineReadOnly)(_this, "providerConfigs", Object.freeze(providerConfigs));
|
469 | (0, properties_1.defineReadOnly)(_this, "quorum", quorum);
|
470 | _this._highestBlockNumber = -1;
|
471 | return _this;
|
472 | }
|
473 | FallbackProvider.prototype.detectNetwork = function () {
|
474 | return __awaiter(this, void 0, void 0, function () {
|
475 | var networks;
|
476 | return __generator(this, function (_a) {
|
477 | switch (_a.label) {
|
478 | case 0: return [4 , Promise.all(this.providerConfigs.map(function (c) { return c.provider.getNetwork(); }))];
|
479 | case 1:
|
480 | networks = _a.sent();
|
481 | return [2 , checkNetworks(networks)];
|
482 | }
|
483 | });
|
484 | });
|
485 | };
|
486 | FallbackProvider.prototype.perform = function (method, params) {
|
487 | return __awaiter(this, void 0, void 0, function () {
|
488 | var results, i_1, result, processFunc, configs, currentBlockNumber, i, first, _loop_1, this_1, state_1;
|
489 | var _this = this;
|
490 | return __generator(this, function (_a) {
|
491 | switch (_a.label) {
|
492 | case 0:
|
493 | if (!(method === "sendTransaction")) return [3 , 2];
|
494 | return [4 , Promise.all(this.providerConfigs.map(function (c) {
|
495 | return c.provider.sendTransaction(params.signedTransaction).then(function (result) {
|
496 | return result.hash;
|
497 | }, function (error) {
|
498 | return error;
|
499 | });
|
500 | }))];
|
501 | case 1:
|
502 | results = _a.sent();
|
503 |
|
504 | for (i_1 = 0; i_1 < results.length; i_1++) {
|
505 | result = results[i_1];
|
506 | if (typeof (result) === "string") {
|
507 | return [2 , result];
|
508 | }
|
509 | }
|
510 |
|
511 | throw results[0];
|
512 | case 2:
|
513 | if (!(this._highestBlockNumber === -1 && method !== "getBlockNumber")) return [3 , 4];
|
514 | return [4 , this.getBlockNumber()];
|
515 | case 3:
|
516 | _a.sent();
|
517 | _a.label = 4;
|
518 | case 4:
|
519 | processFunc = getProcessFunc(this, method, params);
|
520 | configs = (0, random_1.shuffled)(this.providerConfigs.map(properties_1.shallowCopy));
|
521 | configs.sort(function (a, b) { return (a.priority - b.priority); });
|
522 | currentBlockNumber = this._highestBlockNumber;
|
523 | i = 0;
|
524 | first = true;
|
525 | _loop_1 = function () {
|
526 | var t0, inflightWeight, _loop_2, waiting, results, result, errors;
|
527 | return __generator(this, function (_b) {
|
528 | switch (_b.label) {
|
529 | case 0:
|
530 | t0 = now();
|
531 | inflightWeight = configs.filter(function (c) { return (c.runner && ((t0 - c.start) < c.stallTimeout)); })
|
532 | .reduce(function (accum, c) { return (accum + c.weight); }, 0);
|
533 | _loop_2 = function () {
|
534 | var config = configs[i++];
|
535 | var rid = nextRid++;
|
536 | config.start = now();
|
537 | config.staller = stall(config.stallTimeout);
|
538 | config.staller.wait(function () { config.staller = null; });
|
539 | config.runner = getRunner(config, currentBlockNumber, method, params).then(function (result) {
|
540 | config.done = true;
|
541 | config.result = result;
|
542 | if (_this.listenerCount("debug")) {
|
543 | _this.emit("debug", {
|
544 | action: "request",
|
545 | rid: rid,
|
546 | backend: exposeDebugConfig(config, now()),
|
547 | request: { method: method, params: (0, properties_1.deepCopy)(params) },
|
548 | provider: _this
|
549 | });
|
550 | }
|
551 | }, function (error) {
|
552 | config.done = true;
|
553 | config.error = error;
|
554 | if (_this.listenerCount("debug")) {
|
555 | _this.emit("debug", {
|
556 | action: "request",
|
557 | rid: rid,
|
558 | backend: exposeDebugConfig(config, now()),
|
559 | request: { method: method, params: (0, properties_1.deepCopy)(params) },
|
560 | provider: _this
|
561 | });
|
562 | }
|
563 | });
|
564 | if (this_1.listenerCount("debug")) {
|
565 | this_1.emit("debug", {
|
566 | action: "request",
|
567 | rid: rid,
|
568 | backend: exposeDebugConfig(config, null),
|
569 | request: { method: method, params: (0, properties_1.deepCopy)(params) },
|
570 | provider: this_1
|
571 | });
|
572 | }
|
573 | inflightWeight += config.weight;
|
574 | };
|
575 |
|
576 | while (inflightWeight < this_1.quorum && i < configs.length) {
|
577 | _loop_2();
|
578 | }
|
579 | waiting = [];
|
580 | configs.forEach(function (c) {
|
581 | if (c.done || !c.runner) {
|
582 | return;
|
583 | }
|
584 | waiting.push(c.runner);
|
585 | if (c.staller) {
|
586 | waiting.push(c.staller.getPromise());
|
587 | }
|
588 | });
|
589 | if (!waiting.length) return [3 , 2];
|
590 | return [4 , Promise.race(waiting)];
|
591 | case 1:
|
592 | _b.sent();
|
593 | _b.label = 2;
|
594 | case 2:
|
595 | results = configs.filter(function (c) { return (c.done && c.error == null); });
|
596 | if (!(results.length >= this_1.quorum)) return [3 , 5];
|
597 | result = processFunc(results);
|
598 | if (result !== undefined) {
|
599 |
|
600 | configs.forEach(function (c) {
|
601 | if (c.staller) {
|
602 | c.staller.cancel();
|
603 | }
|
604 | c.cancelled = true;
|
605 | });
|
606 | return [2 , { value: result }];
|
607 | }
|
608 | if (!!first) return [3 , 4];
|
609 | return [4 , stall(100).getPromise()];
|
610 | case 3:
|
611 | _b.sent();
|
612 | _b.label = 4;
|
613 | case 4:
|
614 | first = false;
|
615 | _b.label = 5;
|
616 | case 5:
|
617 | errors = configs.reduce(function (accum, c) {
|
618 | if (!c.done || c.error == null) {
|
619 | return accum;
|
620 | }
|
621 | var code = (c.error).code;
|
622 | if (ForwardErrors.indexOf(code) >= 0) {
|
623 | if (!accum[code]) {
|
624 | accum[code] = { error: c.error, weight: 0 };
|
625 | }
|
626 | accum[code].weight += c.weight;
|
627 | }
|
628 | return accum;
|
629 | }, ({}));
|
630 | Object.keys(errors).forEach(function (errorCode) {
|
631 | var tally = errors[errorCode];
|
632 | if (tally.weight < _this.quorum) {
|
633 | return;
|
634 | }
|
635 |
|
636 | configs.forEach(function (c) {
|
637 | if (c.staller) {
|
638 | c.staller.cancel();
|
639 | }
|
640 | c.cancelled = true;
|
641 | });
|
642 | var e = (tally.error);
|
643 | var props = {};
|
644 | ForwardProperties.forEach(function (name) {
|
645 | if (e[name] == null) {
|
646 | return;
|
647 | }
|
648 | props[name] = e[name];
|
649 | });
|
650 | logger.throwError(e.reason || e.message, errorCode, props);
|
651 | });
|
652 |
|
653 | if (configs.filter(function (c) { return !c.done; }).length === 0) {
|
654 | return [2 , "break"];
|
655 | }
|
656 | return [2 ];
|
657 | }
|
658 | });
|
659 | };
|
660 | this_1 = this;
|
661 | _a.label = 5;
|
662 | case 5:
|
663 | if (!true) return [3 , 7];
|
664 | return [5 , _loop_1()];
|
665 | case 6:
|
666 | state_1 = _a.sent();
|
667 | if (typeof state_1 === "object")
|
668 | return [2 , state_1.value];
|
669 | if (state_1 === "break")
|
670 | return [3 , 7];
|
671 | return [3 , 5];
|
672 | case 7:
|
673 |
|
674 | configs.forEach(function (c) {
|
675 | if (c.staller) {
|
676 | c.staller.cancel();
|
677 | }
|
678 | c.cancelled = true;
|
679 | });
|
680 | return [2 , logger.throwError("failed to meet quorum", logger_1.Logger.errors.SERVER_ERROR, {
|
681 | method: method,
|
682 | params: params,
|
683 |
|
684 |
|
685 | results: configs.map(function (c) { return exposeDebugConfig(c); }),
|
686 | provider: this
|
687 | })];
|
688 | }
|
689 | });
|
690 | });
|
691 | };
|
692 | return FallbackProvider;
|
693 | }(base_provider_1.BaseProvider));
|
694 | exports.FallbackProvider = FallbackProvider;
|
695 |
|
\ | No newline at end of file |