opnet
Version:
The perfect library for building Bitcoin-based applications.
99 lines (98 loc) • 3.18 kB
JavaScript
import getFetcher from '../fetch/fetch.js';
import { jsonThreader } from '../threading/JSONThreader.js';
import { AbstractRpcProvider } from './AbstractRpcProvider.js';
export class JSONRpcProvider extends AbstractRpcProvider {
timeout;
fetcherConfigurations;
useRESTAPI;
useThreadedParsing;
url;
_fetcherWithCleanup;
constructor(url, network, timeout = 20_000, fetcherConfigurations = {
keepAliveTimeout: 30_000,
keepAliveTimeoutThreshold: 30_000,
connections: 128,
pipelining: 2,
}, useRESTAPI = true, useThreadedParsing = true) {
super(network);
this.timeout = timeout;
this.fetcherConfigurations = fetcherConfigurations;
this.useRESTAPI = useRESTAPI;
this.useThreadedParsing = useThreadedParsing;
this.url = this.providerUrl(url);
}
get fetcher() {
if (!this._fetcherWithCleanup) {
this._fetcherWithCleanup = getFetcher(this.fetcherConfigurations);
}
return this._fetcherWithCleanup.fetch;
}
async close() {
if (this._fetcherWithCleanup) {
await this._fetcherWithCleanup.close();
this._fetcherWithCleanup = undefined;
}
}
setFetchMode(useRESTAPI) {
this.useRESTAPI = useRESTAPI;
}
async _send(payload) {
const controller = new AbortController();
const { signal } = controller;
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
const params = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': 'OPNET/1.0',
Accept: 'application/json',
'Accept-Charset': 'utf-8',
'Accept-Language': 'en-US',
Connection: 'Keep-Alive',
},
body: JSON.stringify(payload),
timeout: this.timeout,
signal: signal,
};
try {
const resp = await this.fetcher(this.url, params);
if (!resp.ok) {
throw new Error(`Failed to fetch: ${resp.statusText}`);
}
const fetchedData = await this.parseResponse(resp);
if (!fetchedData) {
throw new Error('No data fetched');
}
return [fetchedData];
}
catch (e) {
const error = e;
if (error.name === 'AbortError') {
throw new Error(`Request timed out after ${this.timeout}ms`);
}
throw e;
}
finally {
clearTimeout(timeoutId);
}
}
providerUrl(url) {
url = url.trim();
if (url.endsWith('/')) {
return url.slice(0, -1);
}
if (url.includes('api/v1/json-rpc')) {
return url;
}
else {
return `${url}/api/v1/json-rpc`;
}
}
async parseResponse(resp) {
if (this.useThreadedParsing) {
const buffer = await resp.arrayBuffer();
return jsonThreader.parseBuffer(buffer);
}
return (await resp.json());
}
}