admin: update dist files

This commit is contained in:
Richard Moore 2023-12-19 04:53:50 -05:00
parent 180221574c
commit f6d155c820
34 changed files with 594 additions and 96 deletions

@ -3,6 +3,11 @@ Change Log
This change log is maintained by `src.ts/_admin/update-changelog.ts` but may also be manually updated.
ethers/v6.9.1 (2023-12-19 04:53)
--------------------------------
- Fix uncatchable issue when sending transactions over JSON-RPC and provide some retry-recovery for missing v ([#4513](https://github.com/ethers-io/ethers.js/issues/4513); [1802215](https://github.com/ethers-io/ethers.js/commit/180221574c5d2af9ad85404af4fab8752d3d5029)).
ethers/v6.9.0 (2023-11-27 06:15)
--------------------------------

80
dist/ethers.js vendored

@ -3,7 +3,7 @@ const __$G = (typeof globalThis !== 'undefined' ? globalThis: typeof window !==
/**
* The current version of Ethers.
*/
const version = "6.9.0";
const version = "6.9.1";
/**
* Property helper functions.
@ -18048,16 +18048,19 @@ class AbstractProvider {
// No explicit network was set and this is our first time
if (this.#networkPromise == null) {
// Detect the current network (shared with all calls)
const detectNetwork = this._detectNetwork().then((network) => {
this.emit("network", network, null);
return network;
}, (error) => {
// Reset the networkPromise on failure, so we will try again
if (this.#networkPromise === detectNetwork) {
this.#networkPromise = null;
const detectNetwork = (async () => {
try {
const network = await this._detectNetwork();
this.emit("network", network, null);
return network;
}
throw error;
});
catch (error) {
if (this.#networkPromise === detectNetwork) {
this.#networkPromise = null;
}
throw error;
}
})();
this.#networkPromise = detectNetwork;
return (await detectNetwork).clone();
}
@ -19444,12 +19447,45 @@ class JsonRpcSigner extends AbstractSigner {
// for it; it should show up very quickly
return await (new Promise((resolve, reject) => {
const timeouts = [1000, 100];
let invalids = 0;
const checkTx = async () => {
// Try getting the transaction
const tx = await this.provider.getTransaction(hash);
if (tx != null) {
resolve(tx.replaceableTransaction(blockNumber));
return;
try {
// Try getting the transaction
const tx = await this.provider.getTransaction(hash);
if (tx != null) {
resolve(tx.replaceableTransaction(blockNumber));
return;
}
}
catch (error) {
// If we were cancelled: stop polling.
// If the data is bad: the node returns bad transactions
// If the network changed: calling again will also fail
// If unsupported: likely destroyed
if (isError(error, "CANCELLED") || isError(error, "BAD_DATA") ||
isError(error, "NETWORK_ERROR" )) {
if (error.info == null) {
error.info = {};
}
error.info.sendTransactionHash = hash;
reject(error);
return;
}
// Stop-gap for misbehaving backends; see #4513
if (isError(error, "INVALID_ARGUMENT")) {
invalids++;
if (error.info == null) {
error.info = {};
}
error.info.sendTransactionHash = hash;
if (invalids > 10) {
reject(error);
return;
}
}
// Notify anyone that cares; but we will try again, since
// it is likely an intermittent service error
this.provider.emit("error", makeError("failed to fetch transation after sending (will try again)", "UNKNOWN_ERROR", { error }));
}
// Wait another 4 seconds
this.provider._setTimeout(() => { checkTx(); }, timeouts.pop() || 4000);
@ -19527,7 +19563,7 @@ class JsonRpcApiProvider extends AbstractProvider {
if (this.#drainTimer) {
return;
}
// If we aren't using batching, no hard in sending it immeidately
// If we aren't using batching, no harm in sending it immediately
const stallTime = (this._getOption("batchMaxCount") === 1) ? 0 : this._getOption("batchStallTime");
this.#drainTimer = setTimeout(() => {
this.#drainTimer = null;
@ -19690,9 +19726,15 @@ class JsonRpcApiProvider extends AbstractProvider {
// If we are ready, use ``send``, which enabled requests to be batched
if (this.ready) {
this.#pendingDetectNetwork = (async () => {
const result = Network.from(getBigInt(await this.send("eth_chainId", [])));
this.#pendingDetectNetwork = null;
return result;
try {
const result = Network.from(getBigInt(await this.send("eth_chainId", [])));
this.#pendingDetectNetwork = null;
return result;
}
catch (error) {
this.#pendingDetectNetwork = null;
throw error;
}
})();
return await this.#pendingDetectNetwork;
}

2
dist/ethers.js.map vendored

File diff suppressed because one or more lines are too long

2
dist/ethers.min.js vendored

File diff suppressed because one or more lines are too long

80
dist/ethers.umd.js vendored

@ -9,7 +9,7 @@ const __$G = (typeof globalThis !== 'undefined' ? globalThis: typeof window !==
/**
* The current version of Ethers.
*/
const version = "6.9.0";
const version = "6.9.1";
/**
* Property helper functions.
@ -18054,16 +18054,19 @@ const __$G = (typeof globalThis !== 'undefined' ? globalThis: typeof window !==
// No explicit network was set and this is our first time
if (this.#networkPromise == null) {
// Detect the current network (shared with all calls)
const detectNetwork = this._detectNetwork().then((network) => {
this.emit("network", network, null);
return network;
}, (error) => {
// Reset the networkPromise on failure, so we will try again
if (this.#networkPromise === detectNetwork) {
this.#networkPromise = null;
const detectNetwork = (async () => {
try {
const network = await this._detectNetwork();
this.emit("network", network, null);
return network;
}
throw error;
});
catch (error) {
if (this.#networkPromise === detectNetwork) {
this.#networkPromise = null;
}
throw error;
}
})();
this.#networkPromise = detectNetwork;
return (await detectNetwork).clone();
}
@ -19450,12 +19453,45 @@ const __$G = (typeof globalThis !== 'undefined' ? globalThis: typeof window !==
// for it; it should show up very quickly
return await (new Promise((resolve, reject) => {
const timeouts = [1000, 100];
let invalids = 0;
const checkTx = async () => {
// Try getting the transaction
const tx = await this.provider.getTransaction(hash);
if (tx != null) {
resolve(tx.replaceableTransaction(blockNumber));
return;
try {
// Try getting the transaction
const tx = await this.provider.getTransaction(hash);
if (tx != null) {
resolve(tx.replaceableTransaction(blockNumber));
return;
}
}
catch (error) {
// If we were cancelled: stop polling.
// If the data is bad: the node returns bad transactions
// If the network changed: calling again will also fail
// If unsupported: likely destroyed
if (isError(error, "CANCELLED") || isError(error, "BAD_DATA") ||
isError(error, "NETWORK_ERROR" )) {
if (error.info == null) {
error.info = {};
}
error.info.sendTransactionHash = hash;
reject(error);
return;
}
// Stop-gap for misbehaving backends; see #4513
if (isError(error, "INVALID_ARGUMENT")) {
invalids++;
if (error.info == null) {
error.info = {};
}
error.info.sendTransactionHash = hash;
if (invalids > 10) {
reject(error);
return;
}
}
// Notify anyone that cares; but we will try again, since
// it is likely an intermittent service error
this.provider.emit("error", makeError("failed to fetch transation after sending (will try again)", "UNKNOWN_ERROR", { error }));
}
// Wait another 4 seconds
this.provider._setTimeout(() => { checkTx(); }, timeouts.pop() || 4000);
@ -19533,7 +19569,7 @@ const __$G = (typeof globalThis !== 'undefined' ? globalThis: typeof window !==
if (this.#drainTimer) {
return;
}
// If we aren't using batching, no hard in sending it immeidately
// If we aren't using batching, no harm in sending it immediately
const stallTime = (this._getOption("batchMaxCount") === 1) ? 0 : this._getOption("batchStallTime");
this.#drainTimer = setTimeout(() => {
this.#drainTimer = null;
@ -19696,9 +19732,15 @@ const __$G = (typeof globalThis !== 'undefined' ? globalThis: typeof window !==
// If we are ready, use ``send``, which enabled requests to be batched
if (this.ready) {
this.#pendingDetectNetwork = (async () => {
const result = Network.from(getBigInt(await this.send("eth_chainId", [])));
this.#pendingDetectNetwork = null;
return result;
try {
const result = Network.from(getBigInt(await this.send("eth_chainId", [])));
this.#pendingDetectNetwork = null;
return result;
}
catch (error) {
this.#pendingDetectNetwork = null;
throw error;
}
})();
return await this.#pendingDetectNetwork;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -100,7 +100,7 @@ const rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s));
/**
* The current version of Ethers.
*/
const version = "6.9.0";
const version = "6.9.1";
/**
* Property helper functions.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=test-provider-jsonrpc.d.ts.map

@ -0,0 +1 @@
{"version":3,"file":"test-provider-jsonrpc.d.ts","sourceRoot":"","sources":["../../src.ts/_tests/test-provider-jsonrpc.ts"],"names":[],"mappings":""}

@ -0,0 +1,160 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const assert_1 = tslib_1.__importDefault(require("assert"));
const index_js_1 = require("../index.js");
const StatusMessages = {
200: "OK",
400: "BAD REQUEST",
500: "SERVER ERROR",
};
const wallet = new index_js_1.Wallet((0, index_js_1.id)("test"));
function createProvider(testFunc) {
let blockNumber = 1;
const ticker = setInterval(() => { blockNumber++; }, 100);
if (ticker.unref) {
ticker.unref();
}
const processReq = (req) => {
let result = testFunc(req.method, req.params, blockNumber);
if (result === undefined) {
switch (req.method) {
case "eth_blockNumber":
result = blockNumber;
break;
case "eth_chainId":
result = "0x1337";
break;
case "eth_accounts":
result = [wallet.address];
break;
default:
console.log("****", req);
return { id: index_js_1.id, error: "unsupported", jsonrpc: "2.0" };
}
}
return { id: req.id, result, jsonrpc: "2.0" };
};
const req = new index_js_1.FetchRequest("http:/\/localhost:8082/");
req.getUrlFunc = async (_req, signal) => {
const req = JSON.parse(_req.hasBody() ? (0, index_js_1.toUtf8String)(_req.body) : "");
let statusCode = 200;
const headers = {};
let resp;
try {
if (Array.isArray(req)) {
resp = req.map((r) => processReq(r));
}
else {
resp = processReq(req);
}
}
catch (error) {
statusCode = 500;
resp = error.message;
}
const body = (0, index_js_1.toUtf8Bytes)(JSON.stringify(resp));
return {
statusCode,
statusMessage: StatusMessages[statusCode],
headers, body
};
};
return new index_js_1.JsonRpcProvider(req, undefined, { cacheTimeout: -1 });
}
describe("Ensure Catchable Errors", function () {
it("Can catch bad broadcast replies", async function () {
this.timeout(15000);
const txInfo = {
chainId: 1337,
gasLimit: 100000,
maxFeePerGas: 2000000000,
maxPriorityFeePerGas: 1000000000,
to: wallet.address,
value: 1,
};
const txSign = await wallet.signTransaction(txInfo);
const txObj = index_js_1.Transaction.from(txSign);
let count = 0;
const provider = createProvider((method, params, blockNumber) => {
switch (method) {
case "eth_sendTransaction":
return txObj.hash;
case "eth_getTransactionByHash": {
count++;
// First time; fail!
if (count === 1) {
throw (0, index_js_1.makeError)("Faux Error", "SERVER_ERROR", {
request: ({})
});
}
// Second time; return null
if (count === 2) {
return null;
}
// Return a valid tx...
const result = Object.assign({}, txObj.toJSON(), txObj.signature.toJSON(), { hash: txObj.hash, from: wallet.address });
// ...eventually mined
if (count > 4) {
result.blockNumber = blockNumber;
result.blockHash = (0, index_js_1.id)("test");
}
return result;
}
}
return undefined;
});
const signer = await provider.getSigner();
const tx = await signer.sendTransaction(txInfo);
(0, assert_1.default)(tx);
});
it("Missing v is recovered", async function () {
this.timeout(15000);
const txInfo = {
chainId: 1337,
gasLimit: 100000,
maxFeePerGas: 2000000000,
maxPriorityFeePerGas: 1000000000,
to: wallet.address,
value: 1,
};
const txSign = await wallet.signTransaction(txInfo);
const txObj = index_js_1.Transaction.from(txSign);
let count = 0;
// A provider which is mocked to return a "missing v"
// in getTransaction
const provider = createProvider((method, params, blockNumber) => {
switch (method) {
case "eth_sendTransaction":
return txObj.hash;
case "eth_getTransactionByHash": {
count++;
// The fully valid tx response
const result = Object.assign({}, txObj.toJSON(), txObj.signature.toJSON(), { hash: txObj.hash, from: wallet.address, sig: null });
// First time; fail with a missing v!
if (count < 2) {
delete result.v;
}
// Debug
result._count = count;
return result;
}
}
return undefined;
});
// Track any "missing v" error
let missingV = null;
provider.on("error", (e) => {
if ((0, index_js_1.isError)(e, "UNKNOWN_ERROR") && (0, index_js_1.isError)(e.error, "INVALID_ARGUMENT")) {
if (e.error.argument === "signature" && e.error.shortMessage === "missing v") {
missingV = e.error;
}
}
});
const signer = await provider.getSigner();
const tx = await signer.sendTransaction(txInfo);
assert_1.default.ok(!!tx, "we got a transaction");
assert_1.default.ok(!!missingV, "missing v error present");
});
});
//# sourceMappingURL=test-provider-jsonrpc.js.map

File diff suppressed because one or more lines are too long

@ -5,5 +5,5 @@ exports.version = void 0;
/**
* The current version of Ethers.
*/
exports.version = "6.9.0";
exports.version = "6.9.1";
//# sourceMappingURL=_version.js.map

File diff suppressed because one or more lines are too long

@ -544,16 +544,19 @@ class AbstractProvider {
// No explicit network was set and this is our first time
if (this.#networkPromise == null) {
// Detect the current network (shared with all calls)
const detectNetwork = this._detectNetwork().then((network) => {
this.emit("network", network, null);
return network;
}, (error) => {
// Reset the networkPromise on failure, so we will try again
if (this.#networkPromise === detectNetwork) {
this.#networkPromise = null;
const detectNetwork = (async () => {
try {
const network = await this._detectNetwork();
this.emit("network", network, null);
return network;
}
throw error;
});
catch (error) {
if (this.#networkPromise === detectNetwork) {
this.#networkPromise = null;
}
throw error;
}
})();
this.#networkPromise = detectNetwork;
return (await detectNetwork).clone();
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -136,12 +136,45 @@ class JsonRpcSigner extends abstract_signer_js_1.AbstractSigner {
// for it; it should show up very quickly
return await (new Promise((resolve, reject) => {
const timeouts = [1000, 100];
let invalids = 0;
const checkTx = async () => {
// Try getting the transaction
const tx = await this.provider.getTransaction(hash);
if (tx != null) {
resolve(tx.replaceableTransaction(blockNumber));
return;
try {
// Try getting the transaction
const tx = await this.provider.getTransaction(hash);
if (tx != null) {
resolve(tx.replaceableTransaction(blockNumber));
return;
}
}
catch (error) {
// If we were cancelled: stop polling.
// If the data is bad: the node returns bad transactions
// If the network changed: calling again will also fail
// If unsupported: likely destroyed
if ((0, index_js_5.isError)(error, "CANCELLED") || (0, index_js_5.isError)(error, "BAD_DATA") ||
(0, index_js_5.isError)(error, "NETWORK_ERROR" || (0, index_js_5.isError)(error, "UNSUPPORTED_OPERATION"))) {
if (error.info == null) {
error.info = {};
}
error.info.sendTransactionHash = hash;
reject(error);
return;
}
// Stop-gap for misbehaving backends; see #4513
if ((0, index_js_5.isError)(error, "INVALID_ARGUMENT")) {
invalids++;
if (error.info == null) {
error.info = {};
}
error.info.sendTransactionHash = hash;
if (invalids > 10) {
reject(error);
return;
}
}
// Notify anyone that cares; but we will try again, since
// it is likely an intermittent service error
this.provider.emit("error", (0, index_js_5.makeError)("failed to fetch transation after sending (will try again)", "UNKNOWN_ERROR", { error }));
}
// Wait another 4 seconds
this.provider._setTimeout(() => { checkTx(); }, timeouts.pop() || 4000);
@ -220,7 +253,7 @@ class JsonRpcApiProvider extends abstract_provider_js_1.AbstractProvider {
if (this.#drainTimer) {
return;
}
// If we aren't using batching, no hard in sending it immeidately
// If we aren't using batching, no harm in sending it immediately
const stallTime = (this._getOption("batchMaxCount") === 1) ? 0 : this._getOption("batchStallTime");
this.#drainTimer = setTimeout(() => {
this.#drainTimer = null;
@ -383,9 +416,15 @@ class JsonRpcApiProvider extends abstract_provider_js_1.AbstractProvider {
// If we are ready, use ``send``, which enabled requests to be batched
if (this.ready) {
this.#pendingDetectNetwork = (async () => {
const result = network_js_1.Network.from((0, index_js_5.getBigInt)(await this.send("eth_chainId", [])));
this.#pendingDetectNetwork = null;
return result;
try {
const result = network_js_1.Network.from((0, index_js_5.getBigInt)(await this.send("eth_chainId", [])));
this.#pendingDetectNetwork = null;
return result;
}
catch (error) {
this.#pendingDetectNetwork = null;
throw error;
}
})();
return await this.#pendingDetectNetwork;
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=test-provider-jsonrpc.d.ts.map

@ -0,0 +1 @@
{"version":3,"file":"test-provider-jsonrpc.d.ts","sourceRoot":"","sources":["../../src.ts/_tests/test-provider-jsonrpc.ts"],"names":[],"mappings":""}

@ -0,0 +1,157 @@
import assert from "assert";
import { id, isError, makeError, toUtf8Bytes, toUtf8String, FetchRequest, JsonRpcProvider, Transaction, Wallet } from "../index.js";
const StatusMessages = {
200: "OK",
400: "BAD REQUEST",
500: "SERVER ERROR",
};
const wallet = new Wallet(id("test"));
function createProvider(testFunc) {
let blockNumber = 1;
const ticker = setInterval(() => { blockNumber++; }, 100);
if (ticker.unref) {
ticker.unref();
}
const processReq = (req) => {
let result = testFunc(req.method, req.params, blockNumber);
if (result === undefined) {
switch (req.method) {
case "eth_blockNumber":
result = blockNumber;
break;
case "eth_chainId":
result = "0x1337";
break;
case "eth_accounts":
result = [wallet.address];
break;
default:
console.log("****", req);
return { id, error: "unsupported", jsonrpc: "2.0" };
}
}
return { id: req.id, result, jsonrpc: "2.0" };
};
const req = new FetchRequest("http:/\/localhost:8082/");
req.getUrlFunc = async (_req, signal) => {
const req = JSON.parse(_req.hasBody() ? toUtf8String(_req.body) : "");
let statusCode = 200;
const headers = {};
let resp;
try {
if (Array.isArray(req)) {
resp = req.map((r) => processReq(r));
}
else {
resp = processReq(req);
}
}
catch (error) {
statusCode = 500;
resp = error.message;
}
const body = toUtf8Bytes(JSON.stringify(resp));
return {
statusCode,
statusMessage: StatusMessages[statusCode],
headers, body
};
};
return new JsonRpcProvider(req, undefined, { cacheTimeout: -1 });
}
describe("Ensure Catchable Errors", function () {
it("Can catch bad broadcast replies", async function () {
this.timeout(15000);
const txInfo = {
chainId: 1337,
gasLimit: 100000,
maxFeePerGas: 2000000000,
maxPriorityFeePerGas: 1000000000,
to: wallet.address,
value: 1,
};
const txSign = await wallet.signTransaction(txInfo);
const txObj = Transaction.from(txSign);
let count = 0;
const provider = createProvider((method, params, blockNumber) => {
switch (method) {
case "eth_sendTransaction":
return txObj.hash;
case "eth_getTransactionByHash": {
count++;
// First time; fail!
if (count === 1) {
throw makeError("Faux Error", "SERVER_ERROR", {
request: ({})
});
}
// Second time; return null
if (count === 2) {
return null;
}
// Return a valid tx...
const result = Object.assign({}, txObj.toJSON(), txObj.signature.toJSON(), { hash: txObj.hash, from: wallet.address });
// ...eventually mined
if (count > 4) {
result.blockNumber = blockNumber;
result.blockHash = id("test");
}
return result;
}
}
return undefined;
});
const signer = await provider.getSigner();
const tx = await signer.sendTransaction(txInfo);
assert(tx);
});
it("Missing v is recovered", async function () {
this.timeout(15000);
const txInfo = {
chainId: 1337,
gasLimit: 100000,
maxFeePerGas: 2000000000,
maxPriorityFeePerGas: 1000000000,
to: wallet.address,
value: 1,
};
const txSign = await wallet.signTransaction(txInfo);
const txObj = Transaction.from(txSign);
let count = 0;
// A provider which is mocked to return a "missing v"
// in getTransaction
const provider = createProvider((method, params, blockNumber) => {
switch (method) {
case "eth_sendTransaction":
return txObj.hash;
case "eth_getTransactionByHash": {
count++;
// The fully valid tx response
const result = Object.assign({}, txObj.toJSON(), txObj.signature.toJSON(), { hash: txObj.hash, from: wallet.address, sig: null });
// First time; fail with a missing v!
if (count < 2) {
delete result.v;
}
// Debug
result._count = count;
return result;
}
}
return undefined;
});
// Track any "missing v" error
let missingV = null;
provider.on("error", (e) => {
if (isError(e, "UNKNOWN_ERROR") && isError(e.error, "INVALID_ARGUMENT")) {
if (e.error.argument === "signature" && e.error.shortMessage === "missing v") {
missingV = e.error;
}
}
});
const signer = await provider.getSigner();
const tx = await signer.sendTransaction(txInfo);
assert.ok(!!tx, "we got a transaction");
assert.ok(!!missingV, "missing v error present");
});
});
//# sourceMappingURL=test-provider-jsonrpc.js.map

File diff suppressed because one or more lines are too long

@ -2,5 +2,5 @@
/**
* The current version of Ethers.
*/
export const version = "6.9.0";
export const version = "6.9.1";
//# sourceMappingURL=_version.js.map

File diff suppressed because one or more lines are too long

@ -540,16 +540,19 @@ export class AbstractProvider {
// No explicit network was set and this is our first time
if (this.#networkPromise == null) {
// Detect the current network (shared with all calls)
const detectNetwork = this._detectNetwork().then((network) => {
this.emit("network", network, null);
return network;
}, (error) => {
// Reset the networkPromise on failure, so we will try again
if (this.#networkPromise === detectNetwork) {
this.#networkPromise = null;
const detectNetwork = (async () => {
try {
const network = await this._detectNetwork();
this.emit("network", network, null);
return network;
}
throw error;
});
catch (error) {
if (this.#networkPromise === detectNetwork) {
this.#networkPromise = null;
}
throw error;
}
})();
this.#networkPromise = detectNetwork;
return (await detectNetwork).clone();
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -16,7 +16,7 @@ import { AbiCoder } from "../abi/index.js";
import { getAddress, resolveAddress } from "../address/index.js";
import { TypedDataEncoder } from "../hash/index.js";
import { accessListify } from "../transaction/index.js";
import { defineProperties, getBigInt, hexlify, isHexString, toQuantity, toUtf8Bytes, makeError, assert, assertArgument, FetchRequest, resolveProperties } from "../utils/index.js";
import { defineProperties, getBigInt, hexlify, isHexString, toQuantity, toUtf8Bytes, isError, makeError, assert, assertArgument, FetchRequest, resolveProperties } from "../utils/index.js";
import { AbstractProvider, UnmanagedSubscriber } from "./abstract-provider.js";
import { AbstractSigner } from "./abstract-signer.js";
import { Network } from "./network.js";
@ -133,12 +133,45 @@ export class JsonRpcSigner extends AbstractSigner {
// for it; it should show up very quickly
return await (new Promise((resolve, reject) => {
const timeouts = [1000, 100];
let invalids = 0;
const checkTx = async () => {
// Try getting the transaction
const tx = await this.provider.getTransaction(hash);
if (tx != null) {
resolve(tx.replaceableTransaction(blockNumber));
return;
try {
// Try getting the transaction
const tx = await this.provider.getTransaction(hash);
if (tx != null) {
resolve(tx.replaceableTransaction(blockNumber));
return;
}
}
catch (error) {
// If we were cancelled: stop polling.
// If the data is bad: the node returns bad transactions
// If the network changed: calling again will also fail
// If unsupported: likely destroyed
if (isError(error, "CANCELLED") || isError(error, "BAD_DATA") ||
isError(error, "NETWORK_ERROR" || isError(error, "UNSUPPORTED_OPERATION"))) {
if (error.info == null) {
error.info = {};
}
error.info.sendTransactionHash = hash;
reject(error);
return;
}
// Stop-gap for misbehaving backends; see #4513
if (isError(error, "INVALID_ARGUMENT")) {
invalids++;
if (error.info == null) {
error.info = {};
}
error.info.sendTransactionHash = hash;
if (invalids > 10) {
reject(error);
return;
}
}
// Notify anyone that cares; but we will try again, since
// it is likely an intermittent service error
this.provider.emit("error", makeError("failed to fetch transation after sending (will try again)", "UNKNOWN_ERROR", { error }));
}
// Wait another 4 seconds
this.provider._setTimeout(() => { checkTx(); }, timeouts.pop() || 4000);
@ -216,7 +249,7 @@ export class JsonRpcApiProvider extends AbstractProvider {
if (this.#drainTimer) {
return;
}
// If we aren't using batching, no hard in sending it immeidately
// If we aren't using batching, no harm in sending it immediately
const stallTime = (this._getOption("batchMaxCount") === 1) ? 0 : this._getOption("batchStallTime");
this.#drainTimer = setTimeout(() => {
this.#drainTimer = null;
@ -379,9 +412,15 @@ export class JsonRpcApiProvider extends AbstractProvider {
// If we are ready, use ``send``, which enabled requests to be batched
if (this.ready) {
this.#pendingDetectNetwork = (async () => {
const result = Network.from(getBigInt(await this.send("eth_chainId", [])));
this.#pendingDetectNetwork = null;
return result;
try {
const result = Network.from(getBigInt(await this.send("eth_chainId", [])));
this.#pendingDetectNetwork = null;
return result;
}
catch (error) {
this.#pendingDetectNetwork = null;
throw error;
}
})();
return await this.#pendingDetectNetwork;
}

File diff suppressed because one or more lines are too long

@ -93,7 +93,7 @@
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"gitHead": "f8f11c754aa2c9b541db73d3bde66a8ffa5146f0",
"gitHead": "180221574c5d2af9ad85404af4fab8752d3d5029",
"homepage": "https://ethers.org",
"keywords": [
"ethereum",
@ -128,8 +128,8 @@
"test-browser": "node lib.esm/_admin/test-browser",
"test-commonjs": "mocha --reporter ./reporter.cjs ./lib.commonjs/_tests/test-*.js",
"test-coverage": "c8 -o output -r lcov -r text mocha --no-color --reporter ./reporter.cjs ./lib.esm/_tests/test-*.js | tee output/summary.txt",
"test-esm": "mocha --reporter ./reporter.cjs ./lib.esm/_tests/test-*.js"
"test-esm": "mocha --trace-warnings --reporter ./reporter.cjs ./lib.esm/_tests/test-*.js"
},
"sideEffects": false,
"version": "6.9.0"
"version": "6.9.1"
}

@ -3,4 +3,4 @@
/**
* The current version of Ethers.
*/
export const version: string = "6.9.0";
export const version: string = "6.9.1";