| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 | 
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";/** *  A generic interface to a Websocket-like object. */export interface WebSocketLike {    onopen: null | ((...args: Array<any>) => any);    onmessage: null | ((...args: Array<any>) => any);    onerror: null | ((...args: Array<any>) => any);    readyState: number;    send(payload: any): void;    close(code?: number, reason?: string): void;}/** *  A function which can be used to re-create a WebSocket connection *  on disconnect. */export type WebSocketCreator = () => WebSocketLike;/** *  A JSON-RPC provider which is backed by a WebSocket. * *  WebSockets are often preferred because they retain a live connection *  to a server, which permits more instant access to events. * *  However, this incurs higher server infrasturture costs, so additional *  resources may be required to host your own WebSocket nodes and many *  third-party services charge additional fees for WebSocket endpoints. */export class WebSocketProvider extends SocketProvider {    #connect: null | WebSocketCreator;    #websocket: null | WebSocketLike;    get websocket(): WebSocketLike {        if (this.#websocket == null) { throw new Error("websocket closed"); }        return this.#websocket;    }    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();        } else if (typeof(url) === "function") {            this.#connect = url;            this.#websocket = url();        } else {            this.#connect = null;            this.#websocket = url;        }        this.websocket.onopen = async () => {            try {                await this._start()                this.resume();            } catch (error) {                console.log("failed to start WebsocketProvider", error);                // @TODO: now what? Attempt reconnect?            }        };        this.websocket.onmessage = (message: { data: string }) => {            this._processMessage(message.data);        };/*        this.websocket.onclose = (event) => {            // @TODO: What event.code should we reconnect on?            const reconnect = false;            if (reconnect) {                this.pause(true);                if (this.#connect) {                    this.#websocket = this.#connect();                    this.#websocket.onopen = ...                    // @TODO: this requires the super class to rebroadcast; move it there                }                this._reconnect();            }        };*/    }    async _write(message: string): Promise<void> {        this.websocket.send(message);    }    async destroy(): Promise<void> {        if (this.#websocket != null) {            this.#websocket.close();            this.#websocket = null;        }        super.destroy();    }}
 |