1 | "use strict";
|
2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4 | return new (P || (P = Promise))(function (resolve, reject) {
|
5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9 | });
|
10 | };
|
11 | Object.defineProperty(exports, "__esModule", { value: true });
|
12 | exports.Web3Wrapper = void 0;
|
13 | const assert_1 = require("@0x/assert");
|
14 | const json_schemas_1 = require("@0x/json-schemas");
|
15 | const utils_1 = require("@0x/utils");
|
16 | const ethereum_types_1 = require("ethereum-types");
|
17 | const _ = require("lodash");
|
18 | const marshaller_1 = require("./marshaller");
|
19 | const types_1 = require("./types");
|
20 | const utils_2 = require("./utils");
|
21 | const BASE_TEN = 10;
|
22 |
|
23 |
|
24 | const uniqueVersionIds = {
|
25 | geth: 'Geth',
|
26 | ganache: 'EthereumJS TestRPC',
|
27 | };
|
28 |
|
29 |
|
30 |
|
31 | class Web3Wrapper {
|
32 | |
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 | constructor(supportedProvider, callAndTxnDefaults = {}) {
|
40 | |
41 |
|
42 |
|
43 | this.isZeroExWeb3Wrapper = true;
|
44 | this.abiDecoder = new utils_1.AbiDecoder([]);
|
45 | this._supportedProvider = supportedProvider;
|
46 | this._provider = utils_1.providerUtils.standardizeOrThrow(supportedProvider);
|
47 | this._callAndTxnDefaults = callAndTxnDefaults;
|
48 | this._jsonRpcRequestId = 1;
|
49 | }
|
50 | |
51 |
|
52 |
|
53 |
|
54 |
|
55 | static isAddress(address) {
|
56 | return utils_1.addressUtils.isAddress(address);
|
57 | }
|
58 | |
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 | static toUnitAmount(amount, decimals) {
|
67 | assert_1.assert.isValidBaseUnitAmount('amount', amount);
|
68 | assert_1.assert.isNumber('decimals', decimals);
|
69 | const aUnit = new utils_1.BigNumber(BASE_TEN).pow(decimals);
|
70 | const unit = amount.div(aUnit);
|
71 | return unit;
|
72 | }
|
73 | |
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 | static toBaseUnitAmount(amount, decimals) {
|
82 | assert_1.assert.isNumber('decimals', decimals);
|
83 | const unit = new utils_1.BigNumber(BASE_TEN).pow(decimals);
|
84 | const baseUnitAmount = unit.times(amount);
|
85 | const hasDecimals = baseUnitAmount.decimalPlaces() !== 0;
|
86 | if (hasDecimals) {
|
87 | throw new Error(`Invalid unit amount: ${amount.toString(BASE_TEN)} - Too many decimal places`);
|
88 | }
|
89 | return baseUnitAmount;
|
90 | }
|
91 | |
92 |
|
93 |
|
94 |
|
95 |
|
96 | static toWei(ethAmount) {
|
97 | assert_1.assert.isBigNumber('ethAmount', ethAmount);
|
98 | const ETH_DECIMALS = 18;
|
99 | const balanceWei = Web3Wrapper.toBaseUnitAmount(ethAmount, ETH_DECIMALS);
|
100 | return balanceWei;
|
101 | }
|
102 | static _assertBlockParam(blockParam) {
|
103 | if (_.isNumber(blockParam)) {
|
104 | return;
|
105 | }
|
106 | else if (_.isString(blockParam)) {
|
107 | assert_1.assert.doesBelongToStringEnum('blockParam', blockParam, ethereum_types_1.BlockParamLiteral);
|
108 | }
|
109 | }
|
110 | static _assertBlockParamOrString(blockParam) {
|
111 | try {
|
112 | Web3Wrapper._assertBlockParam(blockParam);
|
113 | }
|
114 | catch (err) {
|
115 | try {
|
116 | assert_1.assert.isHexString('blockParam', blockParam);
|
117 | return;
|
118 | }
|
119 | catch (err) {
|
120 | throw new Error(`Expected blockParam to be of type "string | BlockParam", encountered ${blockParam}`);
|
121 | }
|
122 | }
|
123 | }
|
124 | static _normalizeTxReceiptStatus(status) {
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 | if (_.isString(status)) {
|
131 | return utils_2.utils.convertHexToNumber(status);
|
132 | }
|
133 | else if (status === undefined) {
|
134 | return null;
|
135 | }
|
136 | else {
|
137 | return status;
|
138 | }
|
139 | }
|
140 | |
141 |
|
142 |
|
143 |
|
144 | getContractDefaults() {
|
145 | return this._callAndTxnDefaults;
|
146 | }
|
147 | |
148 |
|
149 |
|
150 |
|
151 | getProvider() {
|
152 | return this._supportedProvider;
|
153 | }
|
154 | |
155 |
|
156 |
|
157 |
|
158 | setProvider(supportedProvider) {
|
159 | const provider = utils_1.providerUtils.standardizeOrThrow(supportedProvider);
|
160 | this._provider = provider;
|
161 | }
|
162 | |
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 | isSenderAddressAvailableAsync(senderAddress) {
|
170 | return __awaiter(this, void 0, void 0, function* () {
|
171 | assert_1.assert.isETHAddressHex('senderAddress', senderAddress);
|
172 | const addresses = yield this.getAvailableAddressesAsync();
|
173 | const normalizedAddress = senderAddress.toLowerCase();
|
174 | return _.includes(addresses, normalizedAddress);
|
175 | });
|
176 | }
|
177 | |
178 |
|
179 |
|
180 |
|
181 | getNodeVersionAsync() {
|
182 | return __awaiter(this, void 0, void 0, function* () {
|
183 | const nodeVersion = yield this.sendRawPayloadAsync({ method: 'web3_clientVersion' });
|
184 | return nodeVersion;
|
185 | });
|
186 | }
|
187 | |
188 |
|
189 |
|
190 |
|
191 | getNetworkIdAsync() {
|
192 | return __awaiter(this, void 0, void 0, function* () {
|
193 | const networkIdStr = yield this.sendRawPayloadAsync({ method: 'net_version' });
|
194 | const networkId = _.parseInt(networkIdStr);
|
195 | return networkId;
|
196 | });
|
197 | }
|
198 | |
199 |
|
200 |
|
201 |
|
202 | getChainIdAsync() {
|
203 | return __awaiter(this, void 0, void 0, function* () {
|
204 | const chainIdStr = yield this.sendRawPayloadAsync({ method: 'eth_chainId' });
|
205 | const chainId = _.parseInt(chainIdStr);
|
206 | return chainId;
|
207 | });
|
208 | }
|
209 | |
210 |
|
211 |
|
212 |
|
213 | getGasPriceAsync() {
|
214 | return __awaiter(this, void 0, void 0, function* () {
|
215 | const gasPriceStr = yield this.sendRawPayloadAsync({ method: 'eth_gasPrice' });
|
216 | return new utils_1.BigNumber(gasPriceStr);
|
217 | });
|
218 | }
|
219 | |
220 |
|
221 |
|
222 | getBaseFeePerGasAsync() {
|
223 | return __awaiter(this, void 0, void 0, function* () {
|
224 | const rawBlock = yield this.sendRawPayloadAsync({
|
225 | method: 'eth_getBlockByNumber',
|
226 | params: ['pending', false],
|
227 | });
|
228 | const { baseFeePerGas } = rawBlock;
|
229 | return new utils_1.BigNumber(baseFeePerGas || 0);
|
230 | });
|
231 | }
|
232 | |
233 |
|
234 |
|
235 |
|
236 | getMaxPriorityFeePerGasAsync() {
|
237 | return __awaiter(this, void 0, void 0, function* () {
|
238 | const feeStr = yield this.sendRawPayloadAsync({ method: 'eth_maxPriorityFeePerGas' });
|
239 | return new utils_1.BigNumber(feeStr);
|
240 | });
|
241 | }
|
242 | |
243 |
|
244 |
|
245 |
|
246 |
|
247 | getTransactionReceiptIfExistsAsync(txHash) {
|
248 | return __awaiter(this, void 0, void 0, function* () {
|
249 | assert_1.assert.isHexString('txHash', txHash);
|
250 | const transactionReceiptRpc = yield this.sendRawPayloadAsync({
|
251 | method: 'eth_getTransactionReceipt',
|
252 | params: [txHash],
|
253 | });
|
254 |
|
255 |
|
256 |
|
257 | if (transactionReceiptRpc !== null && transactionReceiptRpc.blockNumber !== null) {
|
258 | transactionReceiptRpc.status = Web3Wrapper._normalizeTxReceiptStatus(transactionReceiptRpc.status);
|
259 | const transactionReceipt = marshaller_1.marshaller.unmarshalTransactionReceipt(transactionReceiptRpc);
|
260 | return transactionReceipt;
|
261 | }
|
262 | else {
|
263 | return undefined;
|
264 | }
|
265 | });
|
266 | }
|
267 | |
268 |
|
269 |
|
270 |
|
271 |
|
272 | getTransactionByHashAsync(txHash) {
|
273 | return __awaiter(this, void 0, void 0, function* () {
|
274 | assert_1.assert.isHexString('txHash', txHash);
|
275 | const transactionRpc = yield this.sendRawPayloadAsync({
|
276 | method: 'eth_getTransactionByHash',
|
277 | params: [txHash],
|
278 | });
|
279 | const transaction = marshaller_1.marshaller.unmarshalTransaction(transactionRpc);
|
280 | return transaction;
|
281 | });
|
282 | }
|
283 | |
284 |
|
285 |
|
286 |
|
287 |
|
288 |
|
289 | getBalanceInWeiAsync(owner, defaultBlock) {
|
290 | return __awaiter(this, void 0, void 0, function* () {
|
291 | assert_1.assert.isETHAddressHex('owner', owner);
|
292 | if (defaultBlock !== undefined) {
|
293 | Web3Wrapper._assertBlockParam(defaultBlock);
|
294 | }
|
295 | const marshalledDefaultBlock = marshaller_1.marshaller.marshalBlockParam(defaultBlock);
|
296 | const encodedOwner = marshaller_1.marshaller.marshalAddress(owner);
|
297 | const balanceInWei = yield this.sendRawPayloadAsync({
|
298 | method: 'eth_getBalance',
|
299 | params: [encodedOwner, marshalledDefaultBlock],
|
300 | });
|
301 |
|
302 | return new utils_1.BigNumber(balanceInWei);
|
303 | });
|
304 | }
|
305 | |
306 |
|
307 |
|
308 |
|
309 |
|
310 | doesContractExistAtAddressAsync(address) {
|
311 | return __awaiter(this, void 0, void 0, function* () {
|
312 | assert_1.assert.isETHAddressHex('address', address);
|
313 | const code = yield this.getContractCodeAsync(address);
|
314 |
|
315 | const isCodeEmpty = /^0x0{0,40}$/i.test(code);
|
316 | return !isCodeEmpty;
|
317 | });
|
318 | }
|
319 | |
320 |
|
321 |
|
322 |
|
323 |
|
324 |
|
325 | getContractCodeAsync(address, defaultBlock) {
|
326 | return __awaiter(this, void 0, void 0, function* () {
|
327 | assert_1.assert.isETHAddressHex('address', address);
|
328 | if (defaultBlock !== undefined) {
|
329 | Web3Wrapper._assertBlockParam(defaultBlock);
|
330 | }
|
331 | const marshalledDefaultBlock = marshaller_1.marshaller.marshalBlockParam(defaultBlock);
|
332 | const encodedAddress = marshaller_1.marshaller.marshalAddress(address);
|
333 | const code = yield this.sendRawPayloadAsync({
|
334 | method: 'eth_getCode',
|
335 | params: [encodedAddress, marshalledDefaultBlock],
|
336 | });
|
337 | return code;
|
338 | });
|
339 | }
|
340 | |
341 |
|
342 |
|
343 |
|
344 |
|
345 |
|
346 | getTransactionTraceAsync(txHash, traceParams) {
|
347 | return __awaiter(this, void 0, void 0, function* () {
|
348 | assert_1.assert.isHexString('txHash', txHash);
|
349 | const trace = yield this.sendRawPayloadAsync({
|
350 | method: 'debug_traceTransaction',
|
351 | params: [txHash, traceParams],
|
352 | });
|
353 | return trace;
|
354 | });
|
355 | }
|
356 | |
357 |
|
358 |
|
359 |
|
360 |
|
361 |
|
362 | signMessageAsync(address, message) {
|
363 | return __awaiter(this, void 0, void 0, function* () {
|
364 | assert_1.assert.isETHAddressHex('address', address);
|
365 | assert_1.assert.isString('message', message);
|
366 | const signData = yield this.sendRawPayloadAsync({
|
367 | method: 'eth_sign',
|
368 | params: [address, message],
|
369 | });
|
370 | return signData;
|
371 | });
|
372 | }
|
373 | |
374 |
|
375 |
|
376 |
|
377 |
|
378 |
|
379 | signTypedDataAsync(address, typedData) {
|
380 | return __awaiter(this, void 0, void 0, function* () {
|
381 | assert_1.assert.isETHAddressHex('address', address);
|
382 | assert_1.assert.doesConformToSchema('typedData', typedData, json_schemas_1.schemas.eip712TypedDataSchema);
|
383 |
|
384 | const methodsToTry = ['eth_signTypedData_v4', 'eth_signTypedData_v3', 'eth_signTypedData'];
|
385 | let lastErr;
|
386 | for (const method of methodsToTry) {
|
387 | try {
|
388 | return yield this.sendRawPayloadAsync({
|
389 | method,
|
390 |
|
391 |
|
392 | params: [address, method === 'eth_signTypedData' ? typedData : JSON.stringify(typedData)],
|
393 | });
|
394 | }
|
395 | catch (err) {
|
396 | lastErr = err;
|
397 |
|
398 |
|
399 | if (!/(not handled|does not exist|not supported)/.test(err.message)) {
|
400 | throw err;
|
401 | }
|
402 | }
|
403 | }
|
404 | throw lastErr;
|
405 | });
|
406 | }
|
407 | |
408 |
|
409 |
|
410 |
|
411 | getBlockNumberAsync() {
|
412 | return __awaiter(this, void 0, void 0, function* () {
|
413 | const blockNumberHex = yield this.sendRawPayloadAsync({
|
414 | method: 'eth_blockNumber',
|
415 | params: [],
|
416 | });
|
417 | const blockNumber = utils_2.utils.convertHexToNumberOrNull(blockNumberHex);
|
418 | return blockNumber;
|
419 | });
|
420 | }
|
421 | |
422 |
|
423 |
|
424 |
|
425 |
|
426 |
|
427 | getAccountNonceAsync(address, defaultBlock) {
|
428 | return __awaiter(this, void 0, void 0, function* () {
|
429 | assert_1.assert.isETHAddressHex('address', address);
|
430 | if (defaultBlock !== undefined) {
|
431 | Web3Wrapper._assertBlockParam(defaultBlock);
|
432 | }
|
433 | const marshalledDefaultBlock = marshaller_1.marshaller.marshalBlockParam(defaultBlock);
|
434 | const encodedAddress = marshaller_1.marshaller.marshalAddress(address);
|
435 | const nonceHex = yield this.sendRawPayloadAsync({
|
436 | method: 'eth_getTransactionCount',
|
437 | params: [encodedAddress, marshalledDefaultBlock],
|
438 | });
|
439 | assert_1.assert.isHexString('nonce', nonceHex);
|
440 |
|
441 | return parseInt(nonceHex.substr(2), 16);
|
442 | });
|
443 | }
|
444 | |
445 |
|
446 |
|
447 |
|
448 |
|
449 |
|
450 | getBlockIfExistsAsync(blockParam) {
|
451 | return __awaiter(this, void 0, void 0, function* () {
|
452 | Web3Wrapper._assertBlockParamOrString(blockParam);
|
453 | const encodedBlockParam = marshaller_1.marshaller.marshalBlockParam(blockParam);
|
454 | const method = utils_2.utils.isHexStrict(blockParam) ? 'eth_getBlockByHash' : 'eth_getBlockByNumber';
|
455 | const shouldIncludeTransactionData = false;
|
456 | const blockWithoutTransactionDataWithHexValuesOrNull = yield this.sendRawPayloadAsync({
|
457 | method,
|
458 | params: [encodedBlockParam, shouldIncludeTransactionData],
|
459 | });
|
460 | let blockWithoutTransactionDataIfExists;
|
461 | if (blockWithoutTransactionDataWithHexValuesOrNull !== null) {
|
462 | blockWithoutTransactionDataIfExists = marshaller_1.marshaller.unmarshalIntoBlockWithoutTransactionData(blockWithoutTransactionDataWithHexValuesOrNull);
|
463 | }
|
464 | return blockWithoutTransactionDataIfExists;
|
465 | });
|
466 | }
|
467 | |
468 |
|
469 |
|
470 |
|
471 |
|
472 | getBlockWithTransactionDataAsync(blockParam) {
|
473 | return __awaiter(this, void 0, void 0, function* () {
|
474 | Web3Wrapper._assertBlockParamOrString(blockParam);
|
475 | let encodedBlockParam = blockParam;
|
476 | if (_.isNumber(blockParam)) {
|
477 | encodedBlockParam = utils_2.utils.numberToHex(blockParam);
|
478 | }
|
479 | const method = utils_2.utils.isHexStrict(blockParam) ? 'eth_getBlockByHash' : 'eth_getBlockByNumber';
|
480 | const shouldIncludeTransactionData = true;
|
481 | const blockWithTransactionDataWithHexValues = yield this.sendRawPayloadAsync({
|
482 | method,
|
483 | params: [encodedBlockParam, shouldIncludeTransactionData],
|
484 | });
|
485 | const blockWithoutTransactionData = marshaller_1.marshaller.unmarshalIntoBlockWithTransactionData(blockWithTransactionDataWithHexValues);
|
486 | return blockWithoutTransactionData;
|
487 | });
|
488 | }
|
489 | |
490 |
|
491 |
|
492 |
|
493 |
|
494 | getBlockTimestampAsync(blockParam) {
|
495 | return __awaiter(this, void 0, void 0, function* () {
|
496 | Web3Wrapper._assertBlockParamOrString(blockParam);
|
497 | const blockIfExists = yield this.getBlockIfExistsAsync(blockParam);
|
498 | if (blockIfExists === undefined) {
|
499 | throw new Error(`Failed to fetch block with blockParam: ${JSON.stringify(blockParam)}`);
|
500 | }
|
501 | return blockIfExists.timestamp;
|
502 | });
|
503 | }
|
504 | |
505 |
|
506 |
|
507 |
|
508 | getAvailableAddressesAsync() {
|
509 | return __awaiter(this, void 0, void 0, function* () {
|
510 | const addresses = yield this.sendRawPayloadAsync({
|
511 | method: 'eth_accounts',
|
512 | params: [],
|
513 | });
|
514 | const normalizedAddresses = _.map(addresses, address => address.toLowerCase());
|
515 | return normalizedAddresses;
|
516 | });
|
517 | }
|
518 | |
519 |
|
520 |
|
521 |
|
522 | takeSnapshotAsync() {
|
523 | return __awaiter(this, void 0, void 0, function* () {
|
524 | const snapshotId = Number(yield this.sendRawPayloadAsync({ method: 'evm_snapshot', params: [] }));
|
525 | return snapshotId;
|
526 | });
|
527 | }
|
528 | |
529 |
|
530 |
|
531 |
|
532 |
|
533 | revertSnapshotAsync(snapshotId) {
|
534 | return __awaiter(this, void 0, void 0, function* () {
|
535 | assert_1.assert.isNumber('snapshotId', snapshotId);
|
536 | const didRevert = yield this.sendRawPayloadAsync({ method: 'evm_revert', params: [snapshotId] });
|
537 | return didRevert;
|
538 | });
|
539 | }
|
540 | |
541 |
|
542 |
|
543 | mineBlockAsync() {
|
544 | return __awaiter(this, void 0, void 0, function* () {
|
545 | yield this.sendRawPayloadAsync({ method: 'evm_mine', params: [] });
|
546 | });
|
547 | }
|
548 | |
549 |
|
550 |
|
551 |
|
552 |
|
553 | increaseTimeAsync(timeDelta) {
|
554 | return __awaiter(this, void 0, void 0, function* () {
|
555 | assert_1.assert.isNumber('timeDelta', timeDelta);
|
556 |
|
557 | const version = yield this.getNodeVersionAsync();
|
558 | if (_.includes(version, uniqueVersionIds.geth)) {
|
559 | return this.sendRawPayloadAsync({ method: 'debug_increaseTime', params: [timeDelta] });
|
560 | }
|
561 | else if (_.includes(version, uniqueVersionIds.ganache)) {
|
562 | return this.sendRawPayloadAsync({ method: 'evm_increaseTime', params: [timeDelta] });
|
563 | }
|
564 | else {
|
565 | throw new Error(`Unknown client version: ${version}`);
|
566 | }
|
567 | });
|
568 | }
|
569 | |
570 |
|
571 |
|
572 |
|
573 |
|
574 | getLogsAsync(filter) {
|
575 | return __awaiter(this, void 0, void 0, function* () {
|
576 | if (filter.blockHash !== undefined && (filter.fromBlock !== undefined || filter.toBlock !== undefined)) {
|
577 | throw new Error(`Cannot specify 'blockHash' as well as 'fromBlock'/'toBlock' in the filter supplied to 'getLogsAsync'`);
|
578 | }
|
579 | let fromBlock = filter.fromBlock;
|
580 | if (_.isNumber(fromBlock)) {
|
581 | fromBlock = utils_2.utils.numberToHex(fromBlock);
|
582 | }
|
583 | let toBlock = filter.toBlock;
|
584 | if (_.isNumber(toBlock)) {
|
585 | toBlock = utils_2.utils.numberToHex(toBlock);
|
586 | }
|
587 | const serializedFilter = Object.assign(Object.assign({}, filter), { fromBlock,
|
588 | toBlock });
|
589 | const payload = {
|
590 | method: 'eth_getLogs',
|
591 | params: [serializedFilter],
|
592 | };
|
593 | const rawLogs = yield this.sendRawPayloadAsync(payload);
|
594 | const formattedLogs = _.map(rawLogs, marshaller_1.marshaller.unmarshalLog.bind(marshaller_1.marshaller));
|
595 | return formattedLogs;
|
596 | });
|
597 | }
|
598 | |
599 |
|
600 |
|
601 |
|
602 |
|
603 | estimateGasAsync(txData) {
|
604 | return __awaiter(this, void 0, void 0, function* () {
|
605 | assert_1.assert.doesConformToSchema('txData', txData, json_schemas_1.schemas.txDataSchema);
|
606 | const txDataHex = marshaller_1.marshaller.marshalTxData(txData);
|
607 | const gasHex = yield this.sendRawPayloadAsync({ method: 'eth_estimateGas', params: [txDataHex] });
|
608 | const gas = utils_2.utils.convertHexToNumber(gasHex);
|
609 | return gas;
|
610 | });
|
611 | }
|
612 | |
613 |
|
614 |
|
615 |
|
616 |
|
617 |
|
618 | createAccessListAsync(callData, defaultBlock) {
|
619 | return __awaiter(this, void 0, void 0, function* () {
|
620 | assert_1.assert.doesConformToSchema('callData', callData, json_schemas_1.schemas.callDataSchema, [
|
621 | json_schemas_1.schemas.addressSchema,
|
622 | json_schemas_1.schemas.numberSchema,
|
623 | json_schemas_1.schemas.jsNumber,
|
624 | ]);
|
625 | const rawResult = yield this.sendRawPayloadAsync({
|
626 | method: 'eth_createAccessList',
|
627 | params: [marshaller_1.marshaller.marshalCallData(callData), marshaller_1.marshaller.marshalBlockParam(defaultBlock)],
|
628 | });
|
629 | if (rawResult.error) {
|
630 | throw new Error(rawResult.error);
|
631 | }
|
632 | return {
|
633 | accessList: rawResult.accessList.reduce((o, v) => {
|
634 | o[v.address] = o[v.address] || [];
|
635 | o[v.address].push(...(v.storageKeys || []));
|
636 | return o;
|
637 | },
|
638 |
|
639 | {}),
|
640 |
|
641 | gasUsed: parseInt(rawResult.gasUsed.slice(2), 16),
|
642 | };
|
643 | });
|
644 | }
|
645 | |
646 |
|
647 |
|
648 |
|
649 |
|
650 |
|
651 | callAsync(callData, defaultBlock) {
|
652 | return __awaiter(this, void 0, void 0, function* () {
|
653 | assert_1.assert.doesConformToSchema('callData', callData, json_schemas_1.schemas.callDataSchema);
|
654 | if (defaultBlock !== undefined) {
|
655 | Web3Wrapper._assertBlockParam(defaultBlock);
|
656 | }
|
657 | const marshalledDefaultBlock = marshaller_1.marshaller.marshalBlockParam(defaultBlock);
|
658 | const callDataHex = marshaller_1.marshaller.marshalCallData(callData);
|
659 | const overrides = marshaller_1.marshaller.marshalCallOverrides(callData.overrides || {});
|
660 | const rawCallResult = yield this.sendRawPayloadAsync({
|
661 | method: 'eth_call',
|
662 | params: [callDataHex, marshalledDefaultBlock, ...(Object.keys(overrides).length === 0 ? [] : [overrides])],
|
663 | });
|
664 | return rawCallResult;
|
665 | });
|
666 | }
|
667 | |
668 |
|
669 |
|
670 |
|
671 |
|
672 | sendTransactionAsync(txData) {
|
673 | return __awaiter(this, void 0, void 0, function* () {
|
674 | assert_1.assert.doesConformToSchema('txData', txData, json_schemas_1.schemas.txDataSchema);
|
675 | const txDataHex = marshaller_1.marshaller.marshalTxData(txData);
|
676 | const txHash = yield this.sendRawPayloadAsync({ method: 'eth_sendTransaction', params: [txDataHex] });
|
677 | return txHash;
|
678 | });
|
679 | }
|
680 | |
681 |
|
682 |
|
683 |
|
684 |
|
685 |
|
686 |
|
687 |
|
688 |
|
689 |
|
690 |
|
691 | awaitTransactionMinedAsync(txHash, pollingIntervalMs = 1000, timeoutMs) {
|
692 | return __awaiter(this, void 0, void 0, function* () {
|
693 | assert_1.assert.isHexString('txHash', txHash);
|
694 | assert_1.assert.isNumber('pollingIntervalMs', pollingIntervalMs);
|
695 | if (timeoutMs !== undefined) {
|
696 | assert_1.assert.isNumber('timeoutMs', timeoutMs);
|
697 | }
|
698 |
|
699 | let transactionReceipt = yield this.getTransactionReceiptIfExistsAsync(txHash);
|
700 | if (transactionReceipt !== undefined) {
|
701 | const logsWithDecodedArgs = _.map(transactionReceipt.logs, this.abiDecoder.tryToDecodeLogOrNoop.bind(this.abiDecoder));
|
702 | const transactionReceiptWithDecodedLogArgs = Object.assign(Object.assign({}, transactionReceipt), { logs: logsWithDecodedArgs });
|
703 | return transactionReceiptWithDecodedLogArgs;
|
704 | }
|
705 |
|
706 | let wasTimeoutExceeded = false;
|
707 | if (timeoutMs) {
|
708 | setTimeout(() => (wasTimeoutExceeded = true), timeoutMs);
|
709 | }
|
710 | const txReceiptPromise = new Promise((resolve, reject) => {
|
711 | const intervalId = utils_1.intervalUtils.setAsyncExcludingInterval(() => __awaiter(this, void 0, void 0, function* () {
|
712 | if (wasTimeoutExceeded) {
|
713 | utils_1.intervalUtils.clearAsyncExcludingInterval(intervalId);
|
714 | return reject(types_1.Web3WrapperErrors.TransactionMiningTimeout);
|
715 | }
|
716 | transactionReceipt = yield this.getTransactionReceiptIfExistsAsync(txHash);
|
717 | if (transactionReceipt !== undefined) {
|
718 | utils_1.intervalUtils.clearAsyncExcludingInterval(intervalId);
|
719 | const logsWithDecodedArgs = _.map(transactionReceipt.logs, this.abiDecoder.tryToDecodeLogOrNoop.bind(this.abiDecoder));
|
720 | const transactionReceiptWithDecodedLogArgs = Object.assign(Object.assign({}, transactionReceipt), { logs: logsWithDecodedArgs });
|
721 | resolve(transactionReceiptWithDecodedLogArgs);
|
722 | }
|
723 | }), pollingIntervalMs, (err) => {
|
724 | utils_1.intervalUtils.clearAsyncExcludingInterval(intervalId);
|
725 | reject(err);
|
726 | });
|
727 | });
|
728 | const txReceipt = yield txReceiptPromise;
|
729 | return txReceipt;
|
730 | });
|
731 | }
|
732 | |
733 |
|
734 |
|
735 |
|
736 |
|
737 |
|
738 |
|
739 |
|
740 |
|
741 |
|
742 |
|
743 | awaitTransactionSuccessAsync(txHash, pollingIntervalMs = 1000, timeoutMs) {
|
744 | return __awaiter(this, void 0, void 0, function* () {
|
745 | const receipt = yield this.awaitTransactionMinedAsync(txHash, pollingIntervalMs, timeoutMs);
|
746 | if (receipt.status !== 1) {
|
747 | throw new Error(`Transaction failed: ${txHash}`);
|
748 | }
|
749 | return receipt;
|
750 | });
|
751 | }
|
752 | |
753 |
|
754 |
|
755 |
|
756 |
|
757 |
|
758 |
|
759 |
|
760 | setHeadAsync(blockNumber) {
|
761 | return __awaiter(this, void 0, void 0, function* () {
|
762 | assert_1.assert.isNumber('blockNumber', blockNumber);
|
763 | yield this.sendRawPayloadAsync({ method: 'debug_setHead', params: [utils_2.utils.numberToHex(blockNumber)] });
|
764 | });
|
765 | }
|
766 | |
767 |
|
768 |
|
769 |
|
770 |
|
771 | sendRawPayloadAsync(payload) {
|
772 | return __awaiter(this, void 0, void 0, function* () {
|
773 | if (!payload.method) {
|
774 | throw new Error(`Must supply method in JSONRPCRequestPayload, tried: [${payload}]`);
|
775 | }
|
776 |
|
777 | const payloadWithDefaults = Object.assign({ id: this._jsonRpcRequestId++, params: [], jsonrpc: '2.0' }, payload);
|
778 |
|
779 | const sendAsync = utils_1.promisify(this._provider.sendAsync.bind(this._provider));
|
780 | const response = yield sendAsync(payloadWithDefaults);
|
781 | if (!response) {
|
782 | throw new Error(`No response`);
|
783 | }
|
784 | const errorMessage = response.error ? response.error.message || response.error : undefined;
|
785 | if (errorMessage) {
|
786 | throw new Error(errorMessage);
|
787 | }
|
788 | if (response.result === undefined) {
|
789 | throw new Error(`JSON RPC response has no result`);
|
790 | }
|
791 | return response.result;
|
792 | });
|
793 | }
|
794 | |
795 |
|
796 |
|
797 |
|
798 | getNodeTypeAsync() {
|
799 | return __awaiter(this, void 0, void 0, function* () {
|
800 | const version = yield this.getNodeVersionAsync();
|
801 | if (_.includes(version, uniqueVersionIds.geth)) {
|
802 | return types_1.NodeType.Geth;
|
803 | }
|
804 | else if (_.includes(version, uniqueVersionIds.ganache)) {
|
805 | return types_1.NodeType.Ganache;
|
806 | }
|
807 | else {
|
808 | throw new Error(`Unknown client version: ${version}`);
|
809 | }
|
810 | });
|
811 | }
|
812 | }
|
813 | exports.Web3Wrapper = Web3Wrapper;
|
814 |
|
\ | No newline at end of file |