import { clearTimeout, setTimeout } from "timers"; export default class RpcQueryBase { _network; _query; _options; _promise; _timeoutTimer; _timeout = false; _completed = false; _response; _error; _promiseResolve; constructor({ network, query, options = {}, }) { this._network = network; this._query = query; this._options = options; } get result() { return this._promise; } handeTimeout() { this.resolve(undefined, true); } resolve(data, timeout = false) { clearTimeout(this._timeoutTimer); this._timeout = timeout; this._completed = true; if (timeout) { data = { error: "timeout", }; } this._promiseResolve?.(data); } run() { this._promise = this._promise ?? new Promise((resolve) => { this._promiseResolve = resolve; }); this._timeoutTimer = this._timeoutTimer ?? setTimeout(this.handeTimeout.bind(this), (this._options?.queryTimeout || this._network.queryTimeout) * 1000); this._doRun(); return this; } async _doRun() { try { await this._network.ready; await this._run(); } catch (e) { this._promiseResolve?.({ error: e?.message || e?.error }); } } setupRelayTimeout(reject) { return setTimeout(() => { this._error = "timeout"; reject("timeout"); }, (this._options.relayTimeout || this._network.relayTimeout) * 1000); } async queryRpc(rpc, request) { let timer; return new Promise((resolve, reject) => { rpc // @ts-ignore .request(`${request.module}.${request.method}`, request.data) .then((resp) => { if (resp.error) { throw new Error(resp.error); } clearTimeout(timer); this._response = resp; resolve(null); }) .catch((e) => { this._error = e.message; reject({ error: e.message }); clearTimeout(timer); }); timer = this.setupRelayTimeout(reject); }); } }