UNPKG

@ckb-ccc/core

Version:

Core of CCC - CKBer's Codebase

110 lines (109 loc) 3.61 kB
import { TransportFallback, transportFromUri, } from "./transports/advanced.js"; /** * Applies a transformation function to a value if the transformer is provided. * * @param value - The value to be transformed. * @param transformer - An optional transformation function. * @returns The transformed value if a transformer is provided, otherwise the original value. * * @example * ```typescript * const result = transform(5, (x) => x * 2); // Outputs 10 * const resultWithoutTransformer = transform(5); // Outputs 5 * ``` */ function transform(value, transformer) { if (transformer) { return transformer(value); } return value; } export class RequestorJsonRpc { /** * Creates an instance of ClientJsonRpc. * * @param url_ - The URL of the JSON-RPC server. * @param timeout - The timeout for requests in milliseconds */ constructor(url_, config, onError) { this.url_ = url_; this.onError = onError; this.concurrent = 0; this.pending = []; this.id = 0; this.maxConcurrent = config?.maxConcurrent; this.transport = config?.transport ?? new TransportFallback(Array.from(new Set([url_, ...(config?.fallbacks ?? [])]).values(), (url) => transportFromUri(url, config))); } /** * Returns the URL of the JSON-RPC server. * * @returns The URL of the JSON-RPC server. */ get url() { return this.url_; } /** * request a JSON-RPC method. * * @param rpcMethod - The JSON-RPC method. * @param params - Params for the method. * @param inTransformers - An array of input transformers. * @param outTransformer - An output transformer function. * @returns Method response. */ async request(rpcMethod, params, // eslint-disable-next-line @typescript-eslint/no-explicit-any inTransformers, // eslint-disable-next-line @typescript-eslint/no-explicit-any outTransformer) { const payload = this.buildPayload(rpcMethod, inTransformers ? await Promise.all(params .concat(Array.from(new Array(Math.max(inTransformers.length - params.length, 0)))) .map((v, i) => transform(v, inTransformers[i]))) : params); try { return await transform(await this.requestPayload(payload), outTransformer); } catch (err) { if (!this.onError) { throw err; } await this.onError(err); } } async requestPayload(payload) { if (this.maxConcurrent !== undefined && this.concurrent >= this.maxConcurrent) { const pending = new Promise((resolve) => this.pending.push(resolve)); await pending; } this.concurrent += 1; const res = (await this.transport.request(payload)); this.concurrent -= 1; this.pending.shift()?.(); if (res.id !== payload.id) { throw new Error(`Id mismatched, got ${res.id}, expected ${payload.id}`); } if (res.error) { throw res.error; } return res.result; } /** * Builds a JSON-RPC payload for the given method and parameters. * * @param method - The JSON-RPC method name. * @param req - The parameters for the JSON-RPC method. * @returns The JSON-RPC payload. */ buildPayload(method, req) { return { id: this.id++, method, params: req, jsonrpc: "2.0", }; } }