saepenatus
Version:
Web3-Onboard makes it simple to connect Ethereum hardware and software wallets to your dapp. Features standardised spec compliant web3 providers for all supported wallets, framework agnostic modern javascript UI with code splitting, CSS customization, mul
98 lines (78 loc) • 3.38 kB
text/typescript
import { deepCopy } from "@ethersproject/properties";
import { fetchJson } from "@ethersproject/web";
import { JsonRpcProvider } from "./json-rpc-provider";
// Experimental
export class JsonRpcBatchProvider extends JsonRpcProvider {
_pendingBatchAggregator: NodeJS.Timer;
_pendingBatch: Array<{
request: { method: string, params: Array<any>, id: number, jsonrpc: "2.0" },
resolve: (result: any) => void,
reject: (error: Error) => void
}>;
send(method: string, params: Array<any>): Promise<any> {
const request = {
method: method,
params: params,
id: (this._nextId++),
jsonrpc: "2.0"
};
if (this._pendingBatch == null) {
this._pendingBatch = [ ];
}
const inflightRequest: any = { request, resolve: null, reject: null };
const promise = new Promise((resolve, reject) => {
inflightRequest.resolve = resolve;
inflightRequest.reject = reject;
});
this._pendingBatch.push(inflightRequest);
if (!this._pendingBatchAggregator) {
// Schedule batch for next event loop + short duration
this._pendingBatchAggregator = setTimeout(() => {
// Get teh current batch and clear it, so new requests
// go into the next batch
const batch = this._pendingBatch;
this._pendingBatch = null;
this._pendingBatchAggregator = null;
// Get the request as an array of requests
const request = batch.map((inflight) => inflight.request);
this.emit("debug", {
action: "requestBatch",
request: deepCopy(request),
provider: this
});
return fetchJson(this.connection, JSON.stringify(request)).then((result) => {
this.emit("debug", {
action: "response",
request: request,
response: result,
provider: this
});
// For each result, feed it to the correct Promise, depending
// on whether it was a success or error
batch.forEach((inflightRequest, index) => {
const payload = result[index];
if (payload.error) {
const error = new Error(payload.error.message);
(<any>error).code = payload.error.code;
(<any>error).data = payload.error.data;
inflightRequest.reject(error);
} else {
inflightRequest.resolve(payload.result);
}
});
}, (error) => {
this.emit("debug", {
action: "response",
error: error,
request: request,
provider: this
});
batch.forEach((inflightRequest) => {
inflightRequest.reject(error);
});
});
}, 10);
}
return promise;
}
}