Added timeout to waitForTransaction (#477).
This commit is contained in:
parent
8eb0190d5e
commit
bacc440397
@ -259,7 +259,7 @@ export abstract class Provider implements OnceBlockable {
|
||||
}
|
||||
|
||||
// @TODO: This *could* be implemented here, but would pull in events...
|
||||
abstract waitForTransaction(transactionHash: string, timeout?: number): Promise<TransactionReceipt>;
|
||||
abstract waitForTransaction(transactionHash: string, confirmations?: number, timeout?: number): Promise<TransactionReceipt>;
|
||||
|
||||
readonly _isProvider: boolean;
|
||||
|
||||
|
@ -193,7 +193,8 @@ export class Logger {
|
||||
messageDetails.push(key + "=" + JSON.stringify(params[key].toString()));
|
||||
}
|
||||
});
|
||||
messageDetails.push("version=" + this.version);
|
||||
messageDetails.push(`code=${ code }`);
|
||||
messageDetails.push(`version=${ this.version }`);
|
||||
|
||||
const reason = message;
|
||||
if (messageDetails.length) {
|
||||
|
@ -444,22 +444,42 @@ export class BaseProvider extends Provider {
|
||||
// @TODO: Add .poller which must be an event emitter with a 'start', 'stop' and 'block' event;
|
||||
// this will be used once we move to the WebSocket or other alternatives to polling
|
||||
|
||||
async waitForTransaction(transactionHash: string, confirmations?: number): Promise<TransactionReceipt> {
|
||||
async waitForTransaction(transactionHash: string, confirmations?: number, timeout?: number): Promise<TransactionReceipt> {
|
||||
if (confirmations == null) { confirmations = 1; }
|
||||
|
||||
const receipt = await this.getTransactionReceipt(transactionHash);
|
||||
|
||||
// Receipt is already good
|
||||
if (receipt.confirmations >= confirmations) { return receipt; }
|
||||
if ((receipt ? receipt.confirmations: 0) >= confirmations) { return receipt; }
|
||||
|
||||
// Poll until the receipt is good...
|
||||
return new Promise((resolve) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let timer: NodeJS.Timer = null;
|
||||
let done = false;
|
||||
|
||||
const handler = (receipt: TransactionReceipt) => {
|
||||
if (receipt.confirmations < confirmations) { return; }
|
||||
|
||||
if (timer) { clearTimeout(timer); }
|
||||
if (done) { return; }
|
||||
done = true;
|
||||
|
||||
this.removeListener(transactionHash, handler);
|
||||
resolve(receipt);
|
||||
}
|
||||
this.on(transactionHash, handler);
|
||||
|
||||
if (typeof(timeout) === "number" && timeout > 0) {
|
||||
timer = setTimeout(() => {
|
||||
if (done) { return; }
|
||||
timer = null;
|
||||
done = true;
|
||||
|
||||
this.removeListener(transactionHash, handler);
|
||||
reject(logger.makeError("timeout exceeded", Logger.errors.TIMEOUT, { timeout: timeout }));
|
||||
}, timeout);
|
||||
if (timer.unref) { timer.unref(); }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
import { Network } from "@ethersproject/networks";
|
||||
import { BlockWithTransactions, Provider } from "@ethersproject/abstract-provider";
|
||||
import { Block, BlockWithTransactions, Provider } from "@ethersproject/abstract-provider";
|
||||
import { shuffled } from "@ethersproject/random";
|
||||
import { deepCopy, defineReadOnly, shallowCopy } from "@ethersproject/properties";
|
||||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
@ -56,7 +56,7 @@ function median(values: Array<number>): number {
|
||||
|
||||
function serialize(value: any): string {
|
||||
if (value === null) {
|
||||
return null;
|
||||
return "null";
|
||||
} else if (typeof(value) === "number" || typeof(value) === "boolean") {
|
||||
return JSON.stringify(value);
|
||||
} else if (typeof(value) === "string") {
|
||||
@ -222,6 +222,8 @@ function getProcessFunc(provider: FallbackProvider, method: string, params: { [
|
||||
case "getTransaction":
|
||||
case "getTransactionReceipt":
|
||||
normalize = function(tx: any): string {
|
||||
if (tx == null) { return null; }
|
||||
|
||||
tx = shallowCopy(tx);
|
||||
tx.confirmations = -1;
|
||||
return serialize(tx);
|
||||
@ -233,6 +235,8 @@ function getProcessFunc(provider: FallbackProvider, method: string, params: { [
|
||||
// We drop the confirmations from transactions as it is approximate
|
||||
if (params.includeTransactions) {
|
||||
normalize = function(block: BlockWithTransactions): string {
|
||||
if (block == null) { return null; }
|
||||
|
||||
block = shallowCopy(block);
|
||||
block.transactions = block.transactions.map((tx) => {
|
||||
tx = shallowCopy(tx);
|
||||
@ -241,6 +245,11 @@ function getProcessFunc(provider: FallbackProvider, method: string, params: { [
|
||||
});
|
||||
return serialize(block);
|
||||
};
|
||||
} else {
|
||||
normalize = function(block: Block): string {
|
||||
if (block == null) { return null; }
|
||||
return serialize(block);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -460,7 +469,7 @@ export class FallbackProvider extends BaseProvider {
|
||||
const results = configs.filter((c) => (c.done && c.error == null));
|
||||
if (results.length >= this.quorum) {
|
||||
const result = processFunc(results);
|
||||
if (result != undefined) { return result; }
|
||||
if (result !== undefined) { return result; }
|
||||
}
|
||||
|
||||
// All configs have run to completion; we will never get more data
|
||||
@ -470,8 +479,9 @@ export class FallbackProvider extends BaseProvider {
|
||||
return logger.throwError("failed to meet quorum", Logger.errors.SERVER_ERROR, {
|
||||
method: method,
|
||||
params: params,
|
||||
results: configs.map((c) => exposeDebugConfig(c)),
|
||||
//results: configs.map((c) => c.result),
|
||||
//errors: configs.map((c) => c.error),
|
||||
results: configs.map((c) => exposeDebugConfig(c)),
|
||||
provider: this
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user