Add auto-detected static network support to providers and allow customizing socket provider options (#4199, #4418, #4441).
This commit is contained in:
parent
9e74d14432
commit
4681b83d51
@ -3,6 +3,8 @@ import { connect } from "net";
|
||||
import { SocketProvider } from "./provider-socket.js";
|
||||
|
||||
import type { Socket } from "net";
|
||||
|
||||
import type { JsonRpcApiProviderOptions } from "./provider-jsonrpc.js";
|
||||
import type { Networkish } from "./network.js";
|
||||
|
||||
|
||||
@ -35,8 +37,8 @@ export class IpcSocketProvider extends SocketProvider {
|
||||
*/
|
||||
get socket(): Socket { return this.#socket; }
|
||||
|
||||
constructor(path: string, network?: Networkish) {
|
||||
super(network);
|
||||
constructor(path: string, network?: Networkish, options?: JsonRpcApiProviderOptions) {
|
||||
super(network, options);
|
||||
this.#socket = connect(path);
|
||||
|
||||
this.socket.on("ready", async () => {
|
||||
|
@ -190,7 +190,7 @@ export type DebugEventJsonRpcApiProvider = {
|
||||
*/
|
||||
export type JsonRpcApiProviderOptions = {
|
||||
polling?: boolean;
|
||||
staticNetwork?: null | Network;
|
||||
staticNetwork?: null | boolean | Network;
|
||||
batchStallTime?: number;
|
||||
batchMaxSize?: number;
|
||||
batchMaxCount?: number;
|
||||
@ -463,6 +463,7 @@ export abstract class JsonRpcApiProvider extends AbstractProvider {
|
||||
};
|
||||
|
||||
#network: null | Network;
|
||||
#pendingDetectNetwork: null | Promise<Network>;
|
||||
|
||||
#scheduleDrain(): void {
|
||||
if (this.#drainTimer) { return; }
|
||||
@ -554,6 +555,7 @@ export abstract class JsonRpcApiProvider extends AbstractProvider {
|
||||
this.#drainTimer = null;
|
||||
|
||||
this.#network = null;
|
||||
this.#pendingDetectNetwork = null;
|
||||
|
||||
{
|
||||
let resolve: null | ((value: void) => void) = null;
|
||||
@ -563,9 +565,15 @@ export abstract class JsonRpcApiProvider extends AbstractProvider {
|
||||
this.#notReady = { promise, resolve };
|
||||
}
|
||||
|
||||
// Make sure any static network is compatbile with the provided netwrok
|
||||
const staticNetwork = this._getOption("staticNetwork");
|
||||
if (staticNetwork) {
|
||||
if (typeof(staticNetwork) === "boolean") {
|
||||
assertArgument(!staticNetwork || network !== "any", "staticNetwork cannot be used on special network 'any'", "options", options);
|
||||
if (staticNetwork && network != null) {
|
||||
this.#network = Network.from(network);
|
||||
}
|
||||
|
||||
} else if (staticNetwork) {
|
||||
// Make sure any static network is compatbile with the provided netwrok
|
||||
assertArgument(network == null || staticNetwork.matches(network),
|
||||
"staticNetwork MUST match network object", "options", options);
|
||||
this.#network = staticNetwork;
|
||||
@ -641,36 +649,56 @@ export abstract class JsonRpcApiProvider extends AbstractProvider {
|
||||
*/
|
||||
async _detectNetwork(): Promise<Network> {
|
||||
const network = this._getOption("staticNetwork");
|
||||
if (network) { return network; }
|
||||
if (network) {
|
||||
if (network === true) {
|
||||
if (this.#network) { return this.#network; }
|
||||
} else {
|
||||
return network;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.#pendingDetectNetwork) {
|
||||
return await this.#pendingDetectNetwork;
|
||||
}
|
||||
|
||||
// If we are ready, use ``send``, which enabled requests to be batched
|
||||
if (this.ready) {
|
||||
return Network.from(getBigInt(await this.send("eth_chainId", [ ])));
|
||||
this.#pendingDetectNetwork = (async () => {
|
||||
const result = Network.from(getBigInt(await this.send("eth_chainId", [ ])));
|
||||
this.#pendingDetectNetwork = null;
|
||||
return result;
|
||||
})();
|
||||
return await this.#pendingDetectNetwork;
|
||||
}
|
||||
|
||||
// We are not ready yet; use the primitive _send
|
||||
this.#pendingDetectNetwork = (async () => {
|
||||
const payload: JsonRpcPayload = {
|
||||
id: this.#nextId++, method: "eth_chainId", params: [ ], jsonrpc: "2.0"
|
||||
};
|
||||
|
||||
const payload: JsonRpcPayload = {
|
||||
id: this.#nextId++, method: "eth_chainId", params: [ ], jsonrpc: "2.0"
|
||||
};
|
||||
this.emit("debug", { action: "sendRpcPayload", payload });
|
||||
|
||||
this.emit("debug", { action: "sendRpcPayload", payload });
|
||||
let result: JsonRpcResult | JsonRpcError;
|
||||
try {
|
||||
result = (await this._send(payload))[0];
|
||||
this.#pendingDetectNetwork = null;
|
||||
} catch (error) {
|
||||
this.#pendingDetectNetwork = null;
|
||||
this.emit("debug", { action: "receiveRpcError", error });
|
||||
throw error;
|
||||
}
|
||||
|
||||
let result: JsonRpcResult | JsonRpcError;
|
||||
try {
|
||||
result = (await this._send(payload))[0];
|
||||
} catch (error) {
|
||||
this.emit("debug", { action: "receiveRpcError", error });
|
||||
throw error;
|
||||
}
|
||||
this.emit("debug", { action: "receiveRpcResult", result });
|
||||
|
||||
this.emit("debug", { action: "receiveRpcResult", result });
|
||||
if ("result" in result) {
|
||||
return Network.from(getBigInt(result.result));
|
||||
}
|
||||
|
||||
if ("result" in result) {
|
||||
return Network.from(getBigInt(result.result));
|
||||
}
|
||||
throw this.getRpcError(payload, result);
|
||||
})();
|
||||
|
||||
throw this.getRpcError(payload, result);
|
||||
return await this.#pendingDetectNetwork;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,7 +15,9 @@ import { JsonRpcApiProvider } from "./provider-jsonrpc.js";
|
||||
|
||||
import type { Subscriber, Subscription } from "./abstract-provider.js";
|
||||
import type { EventFilter } from "./provider.js";
|
||||
import type { JsonRpcError, JsonRpcPayload, JsonRpcResult } from "./provider-jsonrpc.js";
|
||||
import type {
|
||||
JsonRpcApiProviderOptions, JsonRpcError, JsonRpcPayload, JsonRpcResult
|
||||
} from "./provider-jsonrpc.js";
|
||||
import type { Networkish } from "./network.js";
|
||||
|
||||
|
||||
@ -194,8 +196,23 @@ export class SocketProvider extends JsonRpcApiProvider {
|
||||
*
|
||||
* If unspecified, the network will be discovered.
|
||||
*/
|
||||
constructor(network?: Networkish) {
|
||||
super(network, { batchMaxCount: 1 });
|
||||
constructor(network?: Networkish, _options?: JsonRpcApiProviderOptions) {
|
||||
// Copy the options
|
||||
const options = Object.assign({ }, (_options != null) ? _options: { });
|
||||
|
||||
// Support for batches is generally not supported for
|
||||
// connection-base providers; if this changes in the future
|
||||
// the _send should be updated to reflect this
|
||||
assertArgument(options.batchMaxCount == null || options.batchMaxCount === 1,
|
||||
"sockets-based providers do not support batches", "options.batchMaxCount", _options);
|
||||
options.batchMaxCount = 1;
|
||||
|
||||
// Socket-based Providers (generally) cannot change their network,
|
||||
// since they have a long-lived connection; but let people override
|
||||
// this if they have just cause.
|
||||
if (options.staticNetwork == null) { options.staticNetwork = true; }
|
||||
|
||||
super(network, options);
|
||||
this.#callbacks = new Map();
|
||||
this.#subs = new Map();
|
||||
this.#pending = new Map();
|
||||
|
@ -4,6 +4,7 @@ import { WebSocket as _WebSocket } from "./ws.js"; /*-browser*/
|
||||
|
||||
import { SocketProvider } from "./provider-socket.js";
|
||||
|
||||
import type { JsonRpcApiProviderOptions} from "./provider-jsonrpc.js";
|
||||
import type { Networkish } from "./network.js";
|
||||
|
||||
/**
|
||||
@ -45,8 +46,8 @@ export class WebSocketProvider extends SocketProvider {
|
||||
return this.#websocket;
|
||||
}
|
||||
|
||||
constructor(url: string | WebSocketLike | WebSocketCreator, network?: Networkish) {
|
||||
super(network);
|
||||
constructor(url: string | WebSocketLike | WebSocketCreator, network?: Networkish, options?: JsonRpcApiProviderOptions) {
|
||||
super(network, options);
|
||||
if (typeof(url) === "string") {
|
||||
this.#connect = () => { return new _WebSocket(url); };
|
||||
this.#websocket = this.#connect();
|
||||
|
Loading…
Reference in New Issue
Block a user