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 | params: [address, typedData],
|
391 | });
|
392 | }
|
393 | catch (err) {
|
394 | lastErr = err;
|
395 |
|
396 |
|
397 | if (!/(not handled|does not exist|not supported)/.test(err.message)) {
|
398 | throw err;
|
399 | }
|
400 | }
|
401 | }
|
402 | throw lastErr;
|
403 | });
|
404 | }
|
405 | |
406 |
|
407 |
|
408 |
|
409 | getBlockNumberAsync() {
|
410 | return __awaiter(this, void 0, void 0, function* () {
|
411 | const blockNumberHex = yield this.sendRawPayloadAsync({
|
412 | method: 'eth_blockNumber',
|
413 | params: [],
|
414 | });
|
415 | const blockNumber = utils_2.utils.convertHexToNumberOrNull(blockNumberHex);
|
416 | return blockNumber;
|
417 | });
|
418 | }
|
419 | |
420 |
|
421 |
|
422 |
|
423 |
|
424 |
|
425 | getAccountNonceAsync(address, defaultBlock) {
|
426 | return __awaiter(this, void 0, void 0, function* () {
|
427 | assert_1.assert.isETHAddressHex('address', address);
|
428 | if (defaultBlock !== undefined) {
|
429 | Web3Wrapper._assertBlockParam(defaultBlock);
|
430 | }
|
431 | const marshalledDefaultBlock = marshaller_1.marshaller.marshalBlockParam(defaultBlock);
|
432 | const encodedAddress = marshaller_1.marshaller.marshalAddress(address);
|
433 | const nonceHex = yield this.sendRawPayloadAsync({
|
434 | method: 'eth_getTransactionCount',
|
435 | params: [encodedAddress, marshalledDefaultBlock],
|
436 | });
|
437 | assert_1.assert.isHexString('nonce', nonceHex);
|
438 |
|
439 | return parseInt(nonceHex.substr(2), 16);
|
440 | });
|
441 | }
|
442 | |
443 |
|
444 |
|
445 |
|
446 |
|
447 |
|
448 | getBlockIfExistsAsync(blockParam) {
|
449 | return __awaiter(this, void 0, void 0, function* () {
|
450 | Web3Wrapper._assertBlockParamOrString(blockParam);
|
451 | const encodedBlockParam = marshaller_1.marshaller.marshalBlockParam(blockParam);
|
452 | const method = utils_2.utils.isHexStrict(blockParam) ? 'eth_getBlockByHash' : 'eth_getBlockByNumber';
|
453 | const shouldIncludeTransactionData = false;
|
454 | const blockWithoutTransactionDataWithHexValuesOrNull = yield this.sendRawPayloadAsync({
|
455 | method,
|
456 | params: [encodedBlockParam, shouldIncludeTransactionData],
|
457 | });
|
458 | let blockWithoutTransactionDataIfExists;
|
459 | if (blockWithoutTransactionDataWithHexValuesOrNull !== null) {
|
460 | blockWithoutTransactionDataIfExists = marshaller_1.marshaller.unmarshalIntoBlockWithoutTransactionData(blockWithoutTransactionDataWithHexValuesOrNull);
|
461 | }
|
462 | return blockWithoutTransactionDataIfExists;
|
463 | });
|
464 | }
|
465 | |
466 |
|
467 |
|
468 |
|
469 |
|
470 | getBlockWithTransactionDataAsync(blockParam) {
|
471 | return __awaiter(this, void 0, void 0, function* () {
|
472 | Web3Wrapper._assertBlockParamOrString(blockParam);
|
473 | let encodedBlockParam = blockParam;
|
474 | if (_.isNumber(blockParam)) {
|
475 | encodedBlockParam = utils_2.utils.numberToHex(blockParam);
|
476 | }
|
477 | const method = utils_2.utils.isHexStrict(blockParam) ? 'eth_getBlockByHash' : 'eth_getBlockByNumber';
|
478 | const shouldIncludeTransactionData = true;
|
479 | const blockWithTransactionDataWithHexValues = yield this.sendRawPayloadAsync({
|
480 | method,
|
481 | params: [encodedBlockParam, shouldIncludeTransactionData],
|
482 | });
|
483 | const blockWithoutTransactionData = marshaller_1.marshaller.unmarshalIntoBlockWithTransactionData(blockWithTransactionDataWithHexValues);
|
484 | return blockWithoutTransactionData;
|
485 | });
|
486 | }
|
487 | |
488 |
|
489 |
|
490 |
|
491 |
|
492 | getBlockTimestampAsync(blockParam) {
|
493 | return __awaiter(this, void 0, void 0, function* () {
|
494 | Web3Wrapper._assertBlockParamOrString(blockParam);
|
495 | const blockIfExists = yield this.getBlockIfExistsAsync(blockParam);
|
496 | if (blockIfExists === undefined) {
|
497 | throw new Error(`Failed to fetch block with blockParam: ${JSON.stringify(blockParam)}`);
|
498 | }
|
499 | return blockIfExists.timestamp;
|
500 | });
|
501 | }
|
502 | |
503 |
|
504 |
|
505 |
|
506 | getAvailableAddressesAsync() {
|
507 | return __awaiter(this, void 0, void 0, function* () {
|
508 | const addresses = yield this.sendRawPayloadAsync({
|
509 | method: 'eth_accounts',
|
510 | params: [],
|
511 | });
|
512 | const normalizedAddresses = _.map(addresses, address => address.toLowerCase());
|
513 | return normalizedAddresses;
|
514 | });
|
515 | }
|
516 | |
517 |
|
518 |
|
519 |
|
520 | takeSnapshotAsync() {
|
521 | return __awaiter(this, void 0, void 0, function* () {
|
522 | const snapshotId = Number(yield this.sendRawPayloadAsync({ method: 'evm_snapshot', params: [] }));
|
523 | return snapshotId;
|
524 | });
|
525 | }
|
526 | |
527 |
|
528 |
|
529 |
|
530 |
|
531 | revertSnapshotAsync(snapshotId) {
|
532 | return __awaiter(this, void 0, void 0, function* () {
|
533 | assert_1.assert.isNumber('snapshotId', snapshotId);
|
534 | const didRevert = yield this.sendRawPayloadAsync({ method: 'evm_revert', params: [snapshotId] });
|
535 | return didRevert;
|
536 | });
|
537 | }
|
538 | |
539 |
|
540 |
|
541 | mineBlockAsync() {
|
542 | return __awaiter(this, void 0, void 0, function* () {
|
543 | yield this.sendRawPayloadAsync({ method: 'evm_mine', params: [] });
|
544 | });
|
545 | }
|
546 | |
547 |
|
548 |
|
549 |
|
550 |
|
551 | increaseTimeAsync(timeDelta) {
|
552 | return __awaiter(this, void 0, void 0, function* () {
|
553 | assert_1.assert.isNumber('timeDelta', timeDelta);
|
554 |
|
555 | const version = yield this.getNodeVersionAsync();
|
556 | if (_.includes(version, uniqueVersionIds.geth)) {
|
557 | return this.sendRawPayloadAsync({ method: 'debug_increaseTime', params: [timeDelta] });
|
558 | }
|
559 | else if (_.includes(version, uniqueVersionIds.ganache)) {
|
560 | return this.sendRawPayloadAsync({ method: 'evm_increaseTime', params: [timeDelta] });
|
561 | }
|
562 | else {
|
563 | throw new Error(`Unknown client version: ${version}`);
|
564 | }
|
565 | });
|
566 | }
|
567 | |
568 |
|
569 |
|
570 |
|
571 |
|
572 | getLogsAsync(filter) {
|
573 | return __awaiter(this, void 0, void 0, function* () {
|
574 | if (filter.blockHash !== undefined && (filter.fromBlock !== undefined || filter.toBlock !== undefined)) {
|
575 | throw new Error(`Cannot specify 'blockHash' as well as 'fromBlock'/'toBlock' in the filter supplied to 'getLogsAsync'`);
|
576 | }
|
577 | let fromBlock = filter.fromBlock;
|
578 | if (_.isNumber(fromBlock)) {
|
579 | fromBlock = utils_2.utils.numberToHex(fromBlock);
|
580 | }
|
581 | let toBlock = filter.toBlock;
|
582 | if (_.isNumber(toBlock)) {
|
583 | toBlock = utils_2.utils.numberToHex(toBlock);
|
584 | }
|
585 | const serializedFilter = Object.assign(Object.assign({}, filter), { fromBlock,
|
586 | toBlock });
|
587 | const payload = {
|
588 | method: 'eth_getLogs',
|
589 | params: [serializedFilter],
|
590 | };
|
591 | const rawLogs = yield this.sendRawPayloadAsync(payload);
|
592 | const formattedLogs = _.map(rawLogs, marshaller_1.marshaller.unmarshalLog.bind(marshaller_1.marshaller));
|
593 | return formattedLogs;
|
594 | });
|
595 | }
|
596 | |
597 |
|
598 |
|
599 |
|
600 |
|
601 | estimateGasAsync(txData) {
|
602 | return __awaiter(this, void 0, void 0, function* () {
|
603 | assert_1.assert.doesConformToSchema('txData', txData, json_schemas_1.schemas.txDataSchema);
|
604 | const txDataHex = marshaller_1.marshaller.marshalTxData(txData);
|
605 | const gasHex = yield this.sendRawPayloadAsync({ method: 'eth_estimateGas', params: [txDataHex] });
|
606 | const gas = utils_2.utils.convertHexToNumber(gasHex);
|
607 | return gas;
|
608 | });
|
609 | }
|
610 | |
611 |
|
612 |
|
613 |
|
614 |
|
615 |
|
616 | createAccessListAsync(callData, defaultBlock) {
|
617 | return __awaiter(this, void 0, void 0, function* () {
|
618 | assert_1.assert.doesConformToSchema('callData', callData, json_schemas_1.schemas.callDataSchema, [
|
619 | json_schemas_1.schemas.addressSchema,
|
620 | json_schemas_1.schemas.numberSchema,
|
621 | json_schemas_1.schemas.jsNumber,
|
622 | ]);
|
623 | const rawResult = yield this.sendRawPayloadAsync({
|
624 | method: 'eth_createAccessList',
|
625 | params: [marshaller_1.marshaller.marshalCallData(callData), marshaller_1.marshaller.marshalBlockParam(defaultBlock)],
|
626 | });
|
627 | if (rawResult.error) {
|
628 | throw new Error(rawResult.error);
|
629 | }
|
630 | return {
|
631 | accessList: rawResult.accessList.reduce((o, v) => {
|
632 | o[v.address] = o[v.address] || [];
|
633 | o[v.address].push(...(v.storageKeys || []));
|
634 | return o;
|
635 | },
|
636 |
|
637 | {}),
|
638 |
|
639 | gasUsed: parseInt(rawResult.gasUsed.slice(2), 16),
|
640 | };
|
641 | });
|
642 | }
|
643 | |
644 |
|
645 |
|
646 |
|
647 |
|
648 |
|
649 | callAsync(callData, defaultBlock) {
|
650 | return __awaiter(this, void 0, void 0, function* () {
|
651 | assert_1.assert.doesConformToSchema('callData', callData, json_schemas_1.schemas.callDataSchema);
|
652 | if (defaultBlock !== undefined) {
|
653 | Web3Wrapper._assertBlockParam(defaultBlock);
|
654 | }
|
655 | const marshalledDefaultBlock = marshaller_1.marshaller.marshalBlockParam(defaultBlock);
|
656 | const callDataHex = marshaller_1.marshaller.marshalCallData(callData);
|
657 | const overrides = marshaller_1.marshaller.marshalCallOverrides(callData.overrides || {});
|
658 | const rawCallResult = yield this.sendRawPayloadAsync({
|
659 | method: 'eth_call',
|
660 | params: [callDataHex, marshalledDefaultBlock, ...(Object.keys(overrides).length === 0 ? [] : [overrides])],
|
661 | });
|
662 | return rawCallResult;
|
663 | });
|
664 | }
|
665 | |
666 |
|
667 |
|
668 |
|
669 |
|
670 | sendTransactionAsync(txData) {
|
671 | return __awaiter(this, void 0, void 0, function* () {
|
672 | assert_1.assert.doesConformToSchema('txData', txData, json_schemas_1.schemas.txDataSchema);
|
673 | const txDataHex = marshaller_1.marshaller.marshalTxData(txData);
|
674 | const txHash = yield this.sendRawPayloadAsync({ method: 'eth_sendTransaction', params: [txDataHex] });
|
675 | return txHash;
|
676 | });
|
677 | }
|
678 | |
679 |
|
680 |
|
681 |
|
682 |
|
683 |
|
684 |
|
685 |
|
686 |
|
687 |
|
688 |
|
689 | awaitTransactionMinedAsync(txHash, pollingIntervalMs = 1000, timeoutMs) {
|
690 | return __awaiter(this, void 0, void 0, function* () {
|
691 | assert_1.assert.isHexString('txHash', txHash);
|
692 | assert_1.assert.isNumber('pollingIntervalMs', pollingIntervalMs);
|
693 | if (timeoutMs !== undefined) {
|
694 | assert_1.assert.isNumber('timeoutMs', timeoutMs);
|
695 | }
|
696 |
|
697 | let transactionReceipt = yield this.getTransactionReceiptIfExistsAsync(txHash);
|
698 | if (transactionReceipt !== undefined) {
|
699 | const logsWithDecodedArgs = _.map(transactionReceipt.logs, this.abiDecoder.tryToDecodeLogOrNoop.bind(this.abiDecoder));
|
700 | const transactionReceiptWithDecodedLogArgs = Object.assign(Object.assign({}, transactionReceipt), { logs: logsWithDecodedArgs });
|
701 | return transactionReceiptWithDecodedLogArgs;
|
702 | }
|
703 |
|
704 | let wasTimeoutExceeded = false;
|
705 | if (timeoutMs) {
|
706 | setTimeout(() => (wasTimeoutExceeded = true), timeoutMs);
|
707 | }
|
708 | const txReceiptPromise = new Promise((resolve, reject) => {
|
709 | const intervalId = utils_1.intervalUtils.setAsyncExcludingInterval(() => __awaiter(this, void 0, void 0, function* () {
|
710 | if (wasTimeoutExceeded) {
|
711 | utils_1.intervalUtils.clearAsyncExcludingInterval(intervalId);
|
712 | return reject(types_1.Web3WrapperErrors.TransactionMiningTimeout);
|
713 | }
|
714 | transactionReceipt = yield this.getTransactionReceiptIfExistsAsync(txHash);
|
715 | if (transactionReceipt !== undefined) {
|
716 | utils_1.intervalUtils.clearAsyncExcludingInterval(intervalId);
|
717 | const logsWithDecodedArgs = _.map(transactionReceipt.logs, this.abiDecoder.tryToDecodeLogOrNoop.bind(this.abiDecoder));
|
718 | const transactionReceiptWithDecodedLogArgs = Object.assign(Object.assign({}, transactionReceipt), { logs: logsWithDecodedArgs });
|
719 | resolve(transactionReceiptWithDecodedLogArgs);
|
720 | }
|
721 | }), pollingIntervalMs, (err) => {
|
722 | utils_1.intervalUtils.clearAsyncExcludingInterval(intervalId);
|
723 | reject(err);
|
724 | });
|
725 | });
|
726 | const txReceipt = yield txReceiptPromise;
|
727 | return txReceipt;
|
728 | });
|
729 | }
|
730 | |
731 |
|
732 |
|
733 |
|
734 |
|
735 |
|
736 |
|
737 |
|
738 |
|
739 |
|
740 |
|
741 | awaitTransactionSuccessAsync(txHash, pollingIntervalMs = 1000, timeoutMs) {
|
742 | return __awaiter(this, void 0, void 0, function* () {
|
743 | const receipt = yield this.awaitTransactionMinedAsync(txHash, pollingIntervalMs, timeoutMs);
|
744 | if (receipt.status !== 1) {
|
745 | throw new Error(`Transaction failed: ${txHash}`);
|
746 | }
|
747 | return receipt;
|
748 | });
|
749 | }
|
750 | |
751 |
|
752 |
|
753 |
|
754 |
|
755 |
|
756 |
|
757 |
|
758 | setHeadAsync(blockNumber) {
|
759 | return __awaiter(this, void 0, void 0, function* () {
|
760 | assert_1.assert.isNumber('blockNumber', blockNumber);
|
761 | yield this.sendRawPayloadAsync({ method: 'debug_setHead', params: [utils_2.utils.numberToHex(blockNumber)] });
|
762 | });
|
763 | }
|
764 | |
765 |
|
766 |
|
767 |
|
768 |
|
769 | sendRawPayloadAsync(payload) {
|
770 | return __awaiter(this, void 0, void 0, function* () {
|
771 | if (!payload.method) {
|
772 | throw new Error(`Must supply method in JSONRPCRequestPayload, tried: [${payload}]`);
|
773 | }
|
774 |
|
775 | const payloadWithDefaults = Object.assign({ id: this._jsonRpcRequestId++, params: [], jsonrpc: '2.0' }, payload);
|
776 |
|
777 | const sendAsync = utils_1.promisify(this._provider.sendAsync.bind(this._provider));
|
778 | const response = yield sendAsync(payloadWithDefaults);
|
779 | if (!response) {
|
780 | throw new Error(`No response`);
|
781 | }
|
782 | const errorMessage = response.error ? response.error.message || response.error : undefined;
|
783 | if (errorMessage) {
|
784 | throw new Error(errorMessage);
|
785 | }
|
786 | if (response.result === undefined) {
|
787 | throw new Error(`JSON RPC response has no result`);
|
788 | }
|
789 | return response.result;
|
790 | });
|
791 | }
|
792 | |
793 |
|
794 |
|
795 |
|
796 | getNodeTypeAsync() {
|
797 | return __awaiter(this, void 0, void 0, function* () {
|
798 | const version = yield this.getNodeVersionAsync();
|
799 | if (_.includes(version, uniqueVersionIds.geth)) {
|
800 | return types_1.NodeType.Geth;
|
801 | }
|
802 | else if (_.includes(version, uniqueVersionIds.ganache)) {
|
803 | return types_1.NodeType.Ganache;
|
804 | }
|
805 | else {
|
806 | throw new Error(`Unknown client version: ${version}`);
|
807 | }
|
808 | });
|
809 | }
|
810 | }
|
811 | exports.Web3Wrapper = Web3Wrapper;
|
812 |
|
\ | No newline at end of file |