@qevm/providers 1.0.1 → 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.
- package/README.md +3 -9
- package/lib/_version.d.ts +1 -1
- package/lib/_version.js +1 -1
- package/lib/base-provider.d.ts +5 -6
- package/lib/base-provider.d.ts.map +1 -1
- package/lib/base-provider.js +1658 -2158
- package/lib/base-provider.js.map +1 -1
- package/lib/browser-ipc-provider.d.ts.map +1 -1
- package/lib/browser-ipc-provider.js +1 -1
- package/lib/browser-ipc-provider.js.map +1 -1
- package/lib/browser-net.d.ts.map +1 -1
- package/lib/browser-net.js +1 -2
- package/lib/browser-net.js.map +1 -1
- package/lib/browser-ws.d.ts.map +1 -1
- package/lib/browser-ws.js +6 -6
- package/lib/browser-ws.js.map +1 -1
- package/lib/fallback-provider.d.ts +1 -1
- package/lib/fallback-provider.d.ts.map +1 -1
- package/lib/fallback-provider.js +354 -452
- package/lib/fallback-provider.js.map +1 -1
- package/lib/formatter.d.ts +4 -4
- package/lib/formatter.d.ts.map +1 -1
- package/lib/formatter.js +135 -132
- package/lib/formatter.js.map +1 -1
- package/lib/index.d.ts +3 -10
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +20 -43
- package/lib/index.js.map +1 -1
- package/lib/ipc-provider.d.ts +1 -1
- package/lib/ipc-provider.d.ts.map +1 -1
- package/lib/ipc-provider.js +24 -42
- package/lib/ipc-provider.js.map +1 -1
- package/lib/json-rpc-batch-provider.d.ts +0 -1
- package/lib/json-rpc-batch-provider.d.ts.map +1 -1
- package/lib/json-rpc-batch-provider.js +29 -50
- package/lib/json-rpc-batch-provider.js.map +1 -1
- package/lib/json-rpc-provider.d.ts +3 -3
- package/lib/json-rpc-provider.d.ts.map +1 -1
- package/lib/json-rpc-provider.js +417 -518
- package/lib/json-rpc-provider.js.map +1 -1
- package/lib/url-json-rpc-provider.d.ts +2 -2
- package/lib/url-json-rpc-provider.d.ts.map +1 -1
- package/lib/url-json-rpc-provider.js +47 -118
- package/lib/url-json-rpc-provider.js.map +1 -1
- package/lib/web3-provider.d.ts +3 -4
- package/lib/web3-provider.d.ts.map +1 -1
- package/lib/web3-provider.js +53 -77
- package/lib/web3-provider.js.map +1 -1
- package/lib/websocket-provider.d.ts +3 -3
- package/lib/websocket-provider.d.ts.map +1 -1
- package/lib/websocket-provider.js +136 -229
- package/lib/websocket-provider.js.map +1 -1
- package/lib/ws.d.ts.map +1 -1
- package/lib/ws.js +1 -1
- package/lib/ws.js.map +1 -1
- package/package.json +61 -55
- package/src.ts/_version.ts +1 -1
- package/src.ts/base-provider.ts +1427 -654
- package/src.ts/browser-ipc-provider.ts +1 -3
- package/src.ts/browser-net.ts +1 -1
- package/src.ts/browser-ws.ts +14 -8
- package/src.ts/fallback-provider.ts +379 -202
- package/src.ts/formatter.ts +163 -83
- package/src.ts/index.ts +54 -68
- package/src.ts/ipc-provider.ts +8 -7
- package/src.ts/json-rpc-batch-provider.ts +49 -45
- package/src.ts/json-rpc-provider.ts +597 -248
- package/src.ts/url-json-rpc-provider.ts +35 -16
- package/src.ts/web3-provider.ts +87 -54
- package/src.ts/websocket-provider.ts +125 -67
- package/src.ts/ws.ts +1 -1
- package/lib/alchemy-provider.d.ts +0 -17
- package/lib/alchemy-provider.d.ts.map +0 -1
- package/lib/alchemy-provider.js +0 -112
- package/lib/alchemy-provider.js.map +0 -1
- package/lib/ankr-provider.d.ts +0 -10
- package/lib/ankr-provider.d.ts.map +0 -1
- package/lib/ankr-provider.js +0 -79
- package/lib/ankr-provider.js.map +0 -1
- package/lib/cloudflare-provider.d.ts +0 -8
- package/lib/cloudflare-provider.d.ts.map +0 -1
- package/lib/cloudflare-provider.js +0 -100
- package/lib/cloudflare-provider.js.map +0 -1
- package/lib/etherscan-provider.d.ts +0 -18
- package/lib/etherscan-provider.d.ts.map +0 -1
- package/lib/etherscan-provider.js +0 -528
- package/lib/etherscan-provider.js.map +0 -1
- package/lib/infura-provider.d.ts +0 -21
- package/lib/infura-provider.d.ts.map +0 -1
- package/lib/infura-provider.js +0 -141
- package/lib/infura-provider.js.map +0 -1
- package/lib/nodesmith-provider.d.ts +0 -7
- package/lib/nodesmith-provider.d.ts.map +0 -1
- package/lib/nodesmith-provider.js +0 -64
- package/lib/nodesmith-provider.js.map +0 -1
- package/lib/pocket-provider.d.ts +0 -12
- package/lib/pocket-provider.d.ts.map +0 -1
- package/lib/pocket-provider.js +0 -98
- package/lib/pocket-provider.js.map +0 -1
- package/src.ts/alchemy-provider.ts +0 -101
- package/src.ts/ankr-provider.ts +0 -68
- package/src.ts/cloudflare-provider.ts +0 -42
- package/src.ts/etherscan-provider.ts +0 -454
- package/src.ts/infura-provider.ts +0 -143
- package/src.ts/nodesmith-provider.ts +0 -50
- package/src.ts/pocket-provider.ts +0 -93
package/lib/fallback-provider.js
CHANGED
|
@@ -1,83 +1,37 @@
|
|
|
1
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
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
3
|
exports.FallbackProvider = void 0;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
function now() {
|
|
4
|
+
const abstract_provider_1 = require("@qevm/abstract-provider");
|
|
5
|
+
const bignumber_1 = require("@qevm/bignumber");
|
|
6
|
+
const bytes_1 = require("@qevm/bytes");
|
|
7
|
+
const properties_1 = require("@qevm/properties");
|
|
8
|
+
const random_1 = require("@qevm/random");
|
|
9
|
+
const web_1 = require("@qevm/web");
|
|
10
|
+
const base_provider_1 = require("./base-provider");
|
|
11
|
+
const formatter_1 = require("./formatter");
|
|
12
|
+
const logger_1 = require("@qevm/logger");
|
|
13
|
+
const _version_1 = require("./_version");
|
|
14
|
+
const logger = new logger_1.Logger(_version_1.version);
|
|
15
|
+
function now() {
|
|
16
|
+
return new Date().getTime();
|
|
17
|
+
}
|
|
67
18
|
// Returns to network as long as all agree, or null if any is null.
|
|
68
19
|
// Throws an error if any two networks do not match.
|
|
69
20
|
function checkNetworks(networks) {
|
|
70
|
-
|
|
71
|
-
for (
|
|
72
|
-
|
|
21
|
+
let result = null;
|
|
22
|
+
for (let i = 0; i < networks.length; i++) {
|
|
23
|
+
const network = networks[i];
|
|
73
24
|
// Null! We do not know our network; bail.
|
|
74
25
|
if (network == null) {
|
|
75
26
|
return null;
|
|
76
27
|
}
|
|
77
28
|
if (result) {
|
|
78
29
|
// Make sure the network matches the previous networks
|
|
79
|
-
if (!(result.name === network.name &&
|
|
80
|
-
|
|
30
|
+
if (!(result.name === network.name &&
|
|
31
|
+
result.chainId === network.chainId &&
|
|
32
|
+
(result.ensAddress === network.ensAddress ||
|
|
33
|
+
(result.ensAddress == null &&
|
|
34
|
+
network.ensAddress == null)))) {
|
|
81
35
|
logger.throwArgumentError("provider mismatch", "networks", networks);
|
|
82
36
|
}
|
|
83
37
|
}
|
|
@@ -89,13 +43,13 @@ function checkNetworks(networks) {
|
|
|
89
43
|
}
|
|
90
44
|
function median(values, maxDelta) {
|
|
91
45
|
values = values.slice().sort();
|
|
92
|
-
|
|
46
|
+
const middle = Math.floor(values.length / 2);
|
|
93
47
|
// Odd length; take the middle
|
|
94
48
|
if (values.length % 2) {
|
|
95
49
|
return values[middle];
|
|
96
50
|
}
|
|
97
51
|
// Even length; take the average of the two middle
|
|
98
|
-
|
|
52
|
+
const a = values[middle - 1], b = values[middle];
|
|
99
53
|
if (maxDelta != null && Math.abs(a - b) > maxDelta) {
|
|
100
54
|
return null;
|
|
101
55
|
}
|
|
@@ -105,41 +59,44 @@ function serialize(value) {
|
|
|
105
59
|
if (value === null) {
|
|
106
60
|
return "null";
|
|
107
61
|
}
|
|
108
|
-
else if (typeof
|
|
62
|
+
else if (typeof value === "number" || typeof value === "boolean") {
|
|
109
63
|
return JSON.stringify(value);
|
|
110
64
|
}
|
|
111
|
-
else if (typeof
|
|
65
|
+
else if (typeof value === "string") {
|
|
112
66
|
return value;
|
|
113
67
|
}
|
|
114
68
|
else if (bignumber_1.BigNumber.isBigNumber(value)) {
|
|
115
69
|
return value.toString();
|
|
116
70
|
}
|
|
117
71
|
else if (Array.isArray(value)) {
|
|
118
|
-
return JSON.stringify(value.map(
|
|
72
|
+
return JSON.stringify(value.map((i) => serialize(i)));
|
|
119
73
|
}
|
|
120
|
-
else if (typeof
|
|
121
|
-
|
|
74
|
+
else if (typeof value === "object") {
|
|
75
|
+
const keys = Object.keys(value);
|
|
122
76
|
keys.sort();
|
|
123
|
-
return "{" +
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
v =
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
77
|
+
return ("{" +
|
|
78
|
+
keys
|
|
79
|
+
.map((key) => {
|
|
80
|
+
let v = value[key];
|
|
81
|
+
if (typeof v === "function") {
|
|
82
|
+
v = "[function]";
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
v = serialize(v);
|
|
86
|
+
}
|
|
87
|
+
return JSON.stringify(key) + ":" + v;
|
|
88
|
+
})
|
|
89
|
+
.join(",") +
|
|
90
|
+
"}");
|
|
133
91
|
}
|
|
134
|
-
throw new Error("unknown value type: " + typeof
|
|
92
|
+
throw new Error("unknown value type: " + typeof value);
|
|
135
93
|
}
|
|
136
94
|
// Next request ID to use for emitting debug info
|
|
137
|
-
|
|
138
|
-
;
|
|
95
|
+
let nextRid = 1;
|
|
139
96
|
function stall(duration) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
97
|
+
let cancel = null;
|
|
98
|
+
let timer = null;
|
|
99
|
+
let promise = new Promise((resolve) => {
|
|
143
100
|
cancel = function () {
|
|
144
101
|
if (timer) {
|
|
145
102
|
clearTimeout(timer);
|
|
@@ -148,24 +105,24 @@ function stall(duration) {
|
|
|
148
105
|
resolve();
|
|
149
106
|
};
|
|
150
107
|
timer = setTimeout(cancel, duration);
|
|
151
|
-
})
|
|
152
|
-
|
|
108
|
+
});
|
|
109
|
+
const wait = (func) => {
|
|
153
110
|
promise = promise.then(func);
|
|
154
111
|
return promise;
|
|
155
112
|
};
|
|
156
113
|
function getPromise() {
|
|
157
114
|
return promise;
|
|
158
115
|
}
|
|
159
|
-
return { cancel
|
|
116
|
+
return { cancel, getPromise, wait };
|
|
160
117
|
}
|
|
161
|
-
|
|
118
|
+
const ForwardErrors = [
|
|
162
119
|
logger_1.Logger.errors.CALL_EXCEPTION,
|
|
163
120
|
logger_1.Logger.errors.INSUFFICIENT_FUNDS,
|
|
164
121
|
logger_1.Logger.errors.NONCE_EXPIRED,
|
|
165
122
|
logger_1.Logger.errors.REPLACEMENT_UNDERPRICED,
|
|
166
|
-
logger_1.Logger.errors.UNPREDICTABLE_GAS_LIMIT
|
|
123
|
+
logger_1.Logger.errors.UNPREDICTABLE_GAS_LIMIT,
|
|
167
124
|
];
|
|
168
|
-
|
|
125
|
+
const ForwardProperties = [
|
|
169
126
|
"address",
|
|
170
127
|
"args",
|
|
171
128
|
"errorArgs",
|
|
@@ -173,17 +130,16 @@ var ForwardProperties = [
|
|
|
173
130
|
"method",
|
|
174
131
|
"transaction",
|
|
175
132
|
];
|
|
176
|
-
;
|
|
177
133
|
function exposeDebugConfig(config, now) {
|
|
178
|
-
|
|
179
|
-
weight: config.weight
|
|
134
|
+
const result = {
|
|
135
|
+
weight: config.weight,
|
|
180
136
|
};
|
|
181
|
-
Object.defineProperty(result, "provider", { get:
|
|
137
|
+
Object.defineProperty(result, "provider", { get: () => config.provider });
|
|
182
138
|
if (config.start) {
|
|
183
139
|
result.start = config.start;
|
|
184
140
|
}
|
|
185
141
|
if (now) {
|
|
186
|
-
result.duration =
|
|
142
|
+
result.duration = now - config.start;
|
|
187
143
|
}
|
|
188
144
|
if (config.done) {
|
|
189
145
|
if (config.error) {
|
|
@@ -198,18 +154,18 @@ function exposeDebugConfig(config, now) {
|
|
|
198
154
|
function normalizedTally(normalize, quorum) {
|
|
199
155
|
return function (configs) {
|
|
200
156
|
// Count the votes for each result
|
|
201
|
-
|
|
202
|
-
configs.forEach(
|
|
203
|
-
|
|
157
|
+
const tally = {};
|
|
158
|
+
configs.forEach((c) => {
|
|
159
|
+
const value = normalize(c.result);
|
|
204
160
|
if (!tally[value]) {
|
|
205
161
|
tally[value] = { count: 0, result: c.result };
|
|
206
162
|
}
|
|
207
163
|
tally[value].count++;
|
|
208
164
|
});
|
|
209
165
|
// Check for a quorum on any given result
|
|
210
|
-
|
|
211
|
-
for (
|
|
212
|
-
|
|
166
|
+
const keys = Object.keys(tally);
|
|
167
|
+
for (let i = 0; i < keys.length; i++) {
|
|
168
|
+
const check = tally[keys[i]];
|
|
213
169
|
if (check.count >= quorum) {
|
|
214
170
|
return check.result;
|
|
215
171
|
}
|
|
@@ -219,7 +175,7 @@ function normalizedTally(normalize, quorum) {
|
|
|
219
175
|
};
|
|
220
176
|
}
|
|
221
177
|
function getProcessFunc(provider, method, params) {
|
|
222
|
-
|
|
178
|
+
let normalize = serialize;
|
|
223
179
|
switch (method) {
|
|
224
180
|
case "getBlockNumber":
|
|
225
181
|
// Return the median value, unless there is (median + 1) is also
|
|
@@ -227,9 +183,9 @@ function getProcessFunc(provider, method, params) {
|
|
|
227
183
|
// is going to be stale soon. In the event of a malicious node,
|
|
228
184
|
// the lie will be true soon enough.
|
|
229
185
|
return function (configs) {
|
|
230
|
-
|
|
186
|
+
const values = configs.map((c) => c.result);
|
|
231
187
|
// Get the median block number
|
|
232
|
-
|
|
188
|
+
let blockNumber = median(configs.map((c) => c.result), 2);
|
|
233
189
|
if (blockNumber == null) {
|
|
234
190
|
return undefined;
|
|
235
191
|
}
|
|
@@ -249,7 +205,7 @@ function getProcessFunc(provider, method, params) {
|
|
|
249
205
|
// but do not average even entries and choose the higher.
|
|
250
206
|
// Malicious actors must compromise 50% of the nodes to lie.
|
|
251
207
|
return function (configs) {
|
|
252
|
-
|
|
208
|
+
const values = configs.map((c) => c.result);
|
|
253
209
|
values.sort();
|
|
254
210
|
return values[Math.floor(values.length / 2)];
|
|
255
211
|
};
|
|
@@ -257,7 +213,7 @@ function getProcessFunc(provider, method, params) {
|
|
|
257
213
|
// Returns the median price. Malicious actors must compromise at
|
|
258
214
|
// least 50% of the nodes to lie (in a meaningful way).
|
|
259
215
|
return function (configs) {
|
|
260
|
-
return median(configs.map(
|
|
216
|
+
return median(configs.map((c) => c.result));
|
|
261
217
|
};
|
|
262
218
|
// No additional normalizing required; serialize is enough
|
|
263
219
|
case "getBalance":
|
|
@@ -289,7 +245,7 @@ function getProcessFunc(provider, method, params) {
|
|
|
289
245
|
return null;
|
|
290
246
|
}
|
|
291
247
|
block = (0, properties_1.shallowCopy)(block);
|
|
292
|
-
block.transactions = block.transactions.map(
|
|
248
|
+
block.transactions = block.transactions.map((tx) => {
|
|
293
249
|
tx = (0, properties_1.shallowCopy)(tx);
|
|
294
250
|
tx.confirmations = -1;
|
|
295
251
|
return tx;
|
|
@@ -315,142 +271,122 @@ function getProcessFunc(provider, method, params) {
|
|
|
315
271
|
}
|
|
316
272
|
// If we are doing a blockTag query, we need to make sure the backend is
|
|
317
273
|
// caught up to the FallbackProvider, before sending a request to it.
|
|
318
|
-
function waitForSync(config, blockNumber) {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
return resolve(undefined);
|
|
339
|
-
}, 0);
|
|
340
|
-
});
|
|
341
|
-
}, { oncePoll: provider })];
|
|
274
|
+
async function waitForSync(config, blockNumber) {
|
|
275
|
+
const provider = config.provider;
|
|
276
|
+
if ((provider.blockNumber != null && provider.blockNumber >= blockNumber) ||
|
|
277
|
+
blockNumber === -1) {
|
|
278
|
+
return provider;
|
|
279
|
+
}
|
|
280
|
+
return (0, web_1.poll)(() => {
|
|
281
|
+
return new Promise((resolve, reject) => {
|
|
282
|
+
setTimeout(function () {
|
|
283
|
+
// We are synced
|
|
284
|
+
if (provider.blockNumber >= blockNumber) {
|
|
285
|
+
return resolve(provider);
|
|
286
|
+
}
|
|
287
|
+
// We're done; just quit
|
|
288
|
+
if (config.cancelled) {
|
|
289
|
+
return resolve(null);
|
|
290
|
+
}
|
|
291
|
+
// Try again, next block
|
|
292
|
+
return resolve(undefined);
|
|
293
|
+
}, 0);
|
|
342
294
|
});
|
|
343
|
-
});
|
|
295
|
+
}, { oncePoll: provider });
|
|
344
296
|
}
|
|
345
|
-
function getRunner(config, currentBlockNumber, method, params) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
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
|
-
})];
|
|
297
|
+
async function getRunner(config, currentBlockNumber, method, params) {
|
|
298
|
+
let provider = config.provider;
|
|
299
|
+
switch (method) {
|
|
300
|
+
case "getBlockNumber":
|
|
301
|
+
case "getGasPrice":
|
|
302
|
+
return provider[method]();
|
|
303
|
+
case "getEtherPrice":
|
|
304
|
+
if (provider.getEtherPrice) {
|
|
305
|
+
return provider.getEtherPrice();
|
|
420
306
|
}
|
|
421
|
-
|
|
307
|
+
break;
|
|
308
|
+
case "getBalance":
|
|
309
|
+
case "getTransactionCount":
|
|
310
|
+
case "getCode":
|
|
311
|
+
if (params.blockTag && (0, bytes_1.isHexString)(params.blockTag)) {
|
|
312
|
+
provider = await waitForSync(config, currentBlockNumber);
|
|
313
|
+
}
|
|
314
|
+
return provider[method](params.address, params.blockTag || "latest");
|
|
315
|
+
case "getStorageAt":
|
|
316
|
+
if (params.blockTag && (0, bytes_1.isHexString)(params.blockTag)) {
|
|
317
|
+
provider = await waitForSync(config, currentBlockNumber);
|
|
318
|
+
}
|
|
319
|
+
return provider.getStorageAt(params.address, params.position, params.blockTag || "latest");
|
|
320
|
+
case "getBlock":
|
|
321
|
+
if (params.blockTag && (0, bytes_1.isHexString)(params.blockTag)) {
|
|
322
|
+
provider = await waitForSync(config, currentBlockNumber);
|
|
323
|
+
}
|
|
324
|
+
return provider[params.includeTransactions
|
|
325
|
+
? "getBlockWithTransactions"
|
|
326
|
+
: "getBlock"](params.blockTag || params.blockHash);
|
|
327
|
+
case "call":
|
|
328
|
+
case "estimateGas":
|
|
329
|
+
if (params.blockTag && (0, bytes_1.isHexString)(params.blockTag)) {
|
|
330
|
+
provider = await waitForSync(config, currentBlockNumber);
|
|
331
|
+
}
|
|
332
|
+
if (method === "call" && params.blockTag) {
|
|
333
|
+
return provider[method](params.transaction, params.blockTag);
|
|
334
|
+
}
|
|
335
|
+
return provider[method](params.transaction);
|
|
336
|
+
case "getTransaction":
|
|
337
|
+
case "getTransactionReceipt":
|
|
338
|
+
return provider[method](params.transactionHash);
|
|
339
|
+
case "getLogs": {
|
|
340
|
+
let filter = params.filter;
|
|
341
|
+
if ((filter.fromBlock && (0, bytes_1.isHexString)(filter.fromBlock)) ||
|
|
342
|
+
(filter.toBlock && (0, bytes_1.isHexString)(filter.toBlock))) {
|
|
343
|
+
provider = await waitForSync(config, currentBlockNumber);
|
|
344
|
+
}
|
|
345
|
+
return provider.getLogs(filter);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return logger.throwError("unknown method error", logger_1.Logger.errors.UNKNOWN_ERROR, {
|
|
349
|
+
method: method,
|
|
350
|
+
params: params,
|
|
422
351
|
});
|
|
423
352
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
function FallbackProvider(providers, quorum) {
|
|
427
|
-
var _this = this;
|
|
353
|
+
class FallbackProvider extends base_provider_1.BaseProvider {
|
|
354
|
+
constructor(providers, quorum) {
|
|
428
355
|
if (providers.length === 0) {
|
|
429
356
|
logger.throwArgumentError("missing providers", "providers", providers);
|
|
430
357
|
}
|
|
431
|
-
|
|
358
|
+
const providerConfigs = providers.map((configOrProvider, index) => {
|
|
432
359
|
if (abstract_provider_1.Provider.isProvider(configOrProvider)) {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
360
|
+
const stallTimeout = (0, formatter_1.isCommunityResource)(configOrProvider)
|
|
361
|
+
? 2000
|
|
362
|
+
: 750;
|
|
363
|
+
const priority = 1;
|
|
364
|
+
return Object.freeze({
|
|
365
|
+
provider: configOrProvider,
|
|
366
|
+
weight: 1,
|
|
367
|
+
stallTimeout,
|
|
368
|
+
priority,
|
|
369
|
+
});
|
|
436
370
|
}
|
|
437
|
-
|
|
371
|
+
const config = (0, properties_1.shallowCopy)(configOrProvider);
|
|
438
372
|
if (config.priority == null) {
|
|
439
373
|
config.priority = 1;
|
|
440
374
|
}
|
|
441
375
|
if (config.stallTimeout == null) {
|
|
442
|
-
config.stallTimeout = (0, formatter_1.isCommunityResource)(configOrProvider)
|
|
376
|
+
config.stallTimeout = (0, formatter_1.isCommunityResource)(configOrProvider)
|
|
377
|
+
? 2000
|
|
378
|
+
: 750;
|
|
443
379
|
}
|
|
444
380
|
if (config.weight == null) {
|
|
445
381
|
config.weight = 1;
|
|
446
382
|
}
|
|
447
|
-
|
|
383
|
+
const weight = config.weight;
|
|
448
384
|
if (weight % 1 || weight > 512 || weight < 1) {
|
|
449
|
-
logger.throwArgumentError("invalid weight; must be integer in [1, 512]",
|
|
385
|
+
logger.throwArgumentError("invalid weight; must be integer in [1, 512]", `providers[${index}].weight`, weight);
|
|
450
386
|
}
|
|
451
387
|
return Object.freeze(config);
|
|
452
388
|
});
|
|
453
|
-
|
|
389
|
+
const total = providerConfigs.reduce((accum, c) => accum + c.weight, 0);
|
|
454
390
|
if (quorum == null) {
|
|
455
391
|
quorum = total / 2;
|
|
456
392
|
}
|
|
@@ -458,242 +394,208 @@ var FallbackProvider = /** @class */ (function (_super) {
|
|
|
458
394
|
logger.throwArgumentError("quorum will always fail; larger than total weight", "quorum", quorum);
|
|
459
395
|
}
|
|
460
396
|
// Are all providers' networks are known
|
|
461
|
-
|
|
397
|
+
let networkOrReady = checkNetworks(providerConfigs.map((c) => c.provider.network));
|
|
462
398
|
// Not all networks are known; we must stall
|
|
463
399
|
if (networkOrReady == null) {
|
|
464
|
-
networkOrReady = new Promise(
|
|
465
|
-
setTimeout(
|
|
466
|
-
|
|
400
|
+
networkOrReady = new Promise((resolve, reject) => {
|
|
401
|
+
setTimeout(() => {
|
|
402
|
+
this.detectNetwork().then(resolve, reject);
|
|
467
403
|
}, 0);
|
|
468
404
|
});
|
|
469
405
|
}
|
|
470
|
-
|
|
406
|
+
super(networkOrReady);
|
|
471
407
|
// Preserve a copy, so we do not get mutated
|
|
472
|
-
(0, properties_1.defineReadOnly)(
|
|
473
|
-
(0, properties_1.defineReadOnly)(
|
|
474
|
-
|
|
475
|
-
|
|
408
|
+
(0, properties_1.defineReadOnly)(this, "providerConfigs", Object.freeze(providerConfigs));
|
|
409
|
+
(0, properties_1.defineReadOnly)(this, "quorum", quorum);
|
|
410
|
+
this._highestBlockNumber = -1;
|
|
411
|
+
}
|
|
412
|
+
async detectNetwork() {
|
|
413
|
+
const networks = await Promise.all(this.providerConfigs.map((c) => c.provider.getNetwork()));
|
|
414
|
+
return checkNetworks(networks);
|
|
476
415
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
416
|
+
async perform(method, params) {
|
|
417
|
+
// Sending transactions is special; always broadcast it to all backends
|
|
418
|
+
if (method === "sendTransaction") {
|
|
419
|
+
const results = await Promise.all(this.providerConfigs.map((c) => {
|
|
420
|
+
return c.provider
|
|
421
|
+
.sendTransaction(params.signedTransaction)
|
|
422
|
+
.then((result) => {
|
|
423
|
+
return result.hash;
|
|
424
|
+
}, (error) => {
|
|
425
|
+
return error;
|
|
426
|
+
});
|
|
427
|
+
}));
|
|
428
|
+
// Any success is good enough (other errors are likely "already seen" errors
|
|
429
|
+
for (let i = 0; i < results.length; i++) {
|
|
430
|
+
const result = results[i];
|
|
431
|
+
if (typeof result === "string") {
|
|
432
|
+
return result;
|
|
486
433
|
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
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;
|
|
434
|
+
}
|
|
435
|
+
// They were all an error; pick the first error
|
|
436
|
+
throw results[0];
|
|
437
|
+
}
|
|
438
|
+
// We need to make sure we are in sync with our backends, so we need
|
|
439
|
+
// to know this before we can make a lot of calls
|
|
440
|
+
if (this._highestBlockNumber === -1 && method !== "getBlockNumber") {
|
|
441
|
+
await this.getBlockNumber();
|
|
442
|
+
}
|
|
443
|
+
const processFunc = getProcessFunc(this, method, params);
|
|
444
|
+
// Shuffle the providers and then sort them by their priority; we
|
|
445
|
+
// shallowCopy them since we will store the result in them too
|
|
446
|
+
const configs = (0, random_1.shuffled)(this.providerConfigs.map(properties_1.shallowCopy));
|
|
447
|
+
configs.sort((a, b) => a.priority - b.priority);
|
|
448
|
+
const currentBlockNumber = this._highestBlockNumber;
|
|
449
|
+
let i = 0;
|
|
450
|
+
let first = true;
|
|
451
|
+
while (true) {
|
|
452
|
+
const t0 = now();
|
|
453
|
+
// Compute the inflight weight (exclude anything past)
|
|
454
|
+
let inflightWeight = configs
|
|
455
|
+
.filter((c) => c.runner && t0 - c.start < c.stallTimeout)
|
|
456
|
+
.reduce((accum, c) => accum + c.weight, 0);
|
|
457
|
+
// Start running enough to meet quorum
|
|
458
|
+
while (inflightWeight < this.quorum && i < configs.length) {
|
|
459
|
+
const config = configs[i++];
|
|
460
|
+
const rid = nextRid++;
|
|
461
|
+
config.start = now();
|
|
462
|
+
config.staller = stall(config.stallTimeout);
|
|
463
|
+
config.staller.wait(() => {
|
|
464
|
+
config.staller = null;
|
|
465
|
+
});
|
|
466
|
+
config.runner = getRunner(config, currentBlockNumber, method, params).then((result) => {
|
|
467
|
+
config.done = true;
|
|
468
|
+
config.result = result;
|
|
469
|
+
if (this.listenerCount("debug")) {
|
|
470
|
+
this.emit("debug", {
|
|
471
|
+
action: "request",
|
|
472
|
+
rid: rid,
|
|
473
|
+
backend: exposeDebugConfig(config, now()),
|
|
474
|
+
request: {
|
|
475
|
+
method: method,
|
|
476
|
+
params: (0, properties_1.deepCopy)(params),
|
|
477
|
+
},
|
|
478
|
+
provider: this,
|
|
683
479
|
});
|
|
684
|
-
|
|
480
|
+
}
|
|
481
|
+
}, (error) => {
|
|
482
|
+
config.done = true;
|
|
483
|
+
config.error = error;
|
|
484
|
+
if (this.listenerCount("debug")) {
|
|
485
|
+
this.emit("debug", {
|
|
486
|
+
action: "request",
|
|
487
|
+
rid: rid,
|
|
488
|
+
backend: exposeDebugConfig(config, now()),
|
|
489
|
+
request: {
|
|
685
490
|
method: method,
|
|
686
|
-
params: params,
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
491
|
+
params: (0, properties_1.deepCopy)(params),
|
|
492
|
+
},
|
|
493
|
+
provider: this,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
if (this.listenerCount("debug")) {
|
|
498
|
+
this.emit("debug", {
|
|
499
|
+
action: "request",
|
|
500
|
+
rid: rid,
|
|
501
|
+
backend: exposeDebugConfig(config, null),
|
|
502
|
+
request: { method: method, params: (0, properties_1.deepCopy)(params) },
|
|
503
|
+
provider: this,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
inflightWeight += config.weight;
|
|
507
|
+
}
|
|
508
|
+
// Wait for anything meaningful to finish or stall out
|
|
509
|
+
const waiting = [];
|
|
510
|
+
configs.forEach((c) => {
|
|
511
|
+
if (c.done || !c.runner) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
waiting.push(c.runner);
|
|
515
|
+
if (c.staller) {
|
|
516
|
+
waiting.push(c.staller.getPromise());
|
|
692
517
|
}
|
|
693
518
|
});
|
|
519
|
+
if (waiting.length) {
|
|
520
|
+
await Promise.race(waiting);
|
|
521
|
+
}
|
|
522
|
+
// Check the quorum and process the results; the process function
|
|
523
|
+
// may additionally decide the quorum is not met
|
|
524
|
+
const results = configs.filter((c) => c.done && c.error == null);
|
|
525
|
+
if (results.length >= this.quorum) {
|
|
526
|
+
const result = processFunc(results);
|
|
527
|
+
if (result !== undefined) {
|
|
528
|
+
// Shut down any stallers
|
|
529
|
+
configs.forEach((c) => {
|
|
530
|
+
if (c.staller) {
|
|
531
|
+
c.staller.cancel();
|
|
532
|
+
}
|
|
533
|
+
c.cancelled = true;
|
|
534
|
+
});
|
|
535
|
+
return result;
|
|
536
|
+
}
|
|
537
|
+
if (!first) {
|
|
538
|
+
await stall(100).getPromise();
|
|
539
|
+
}
|
|
540
|
+
first = false;
|
|
541
|
+
}
|
|
542
|
+
// No result, check for errors that should be forwarded
|
|
543
|
+
const errors = configs.reduce((accum, c) => {
|
|
544
|
+
if (!c.done || c.error == null) {
|
|
545
|
+
return accum;
|
|
546
|
+
}
|
|
547
|
+
const code = c.error.code;
|
|
548
|
+
if (ForwardErrors.indexOf(code) >= 0) {
|
|
549
|
+
if (!accum[code]) {
|
|
550
|
+
accum[code] = { error: c.error, weight: 0 };
|
|
551
|
+
}
|
|
552
|
+
accum[code].weight += c.weight;
|
|
553
|
+
}
|
|
554
|
+
return accum;
|
|
555
|
+
}, {});
|
|
556
|
+
Object.keys(errors).forEach((errorCode) => {
|
|
557
|
+
const tally = errors[errorCode];
|
|
558
|
+
if (tally.weight < this.quorum) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
// Shut down any stallers
|
|
562
|
+
configs.forEach((c) => {
|
|
563
|
+
if (c.staller) {
|
|
564
|
+
c.staller.cancel();
|
|
565
|
+
}
|
|
566
|
+
c.cancelled = true;
|
|
567
|
+
});
|
|
568
|
+
const e = tally.error;
|
|
569
|
+
const props = {};
|
|
570
|
+
ForwardProperties.forEach((name) => {
|
|
571
|
+
if (e[name] == null) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
props[name] = e[name];
|
|
575
|
+
});
|
|
576
|
+
logger.throwError(e.reason || e.message, errorCode, props);
|
|
577
|
+
});
|
|
578
|
+
// All configs have run to completion; we will never get more data
|
|
579
|
+
if (configs.filter((c) => !c.done).length === 0) {
|
|
580
|
+
break;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
// Shut down any stallers; shouldn't be any
|
|
584
|
+
configs.forEach((c) => {
|
|
585
|
+
if (c.staller) {
|
|
586
|
+
c.staller.cancel();
|
|
587
|
+
}
|
|
588
|
+
c.cancelled = true;
|
|
694
589
|
});
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
590
|
+
return logger.throwError("failed to meet quorum", logger_1.Logger.errors.SERVER_ERROR, {
|
|
591
|
+
method: method,
|
|
592
|
+
params: params,
|
|
593
|
+
//results: configs.map((c) => c.result),
|
|
594
|
+
//errors: configs.map((c) => c.error),
|
|
595
|
+
results: configs.map((c) => exposeDebugConfig(c)),
|
|
596
|
+
provider: this,
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
}
|
|
698
600
|
exports.FallbackProvider = FallbackProvider;
|
|
699
601
|
//# sourceMappingURL=fallback-provider.js.map
|