import logger from "../../logging";
import { fetch } from "cross-fetch";
import { AbortController } from "abort-controller";
const log = logger("rpc");
export async function sendQuery(url, query, config = {}) {
    log.info(`RPC: ${url} executing Query[${query.method}]`);
    const fetchConfig = {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify(query.export()),
    };
    if (config.timeout) {
        const timeoutController = new AbortController();
        setTimeout(() => timeoutController.abort(), config.timeout);
        fetchConfig.signal = timeoutController.signal;
    }
    const response = await fetch(url, fetchConfig);
    if (response.ok) {
        return response.json();
    }
    throw new Error(`Encountered HTTP code ${response.status} while executing Query[${query.method}]`);
}
/**
 * Basic JSON-RPC 2.0 Dispatcher. Contains the basic infrastructure to send out JSON-RPC 2.0 methods.
 * Client interfaces should accept this RpcDispatcher as a constructor parameter.
 *
 * @example
 *
 * ```ts
 * const dispatcher = new RpcDispatcher("http://www.example.com");
 * const result = await dispatcher.execute(new Query({"method": "listplugins"}));
 * ```
 */
export class RpcDispatcher {
    constructor(url) {
        if (!url.startsWith("http://") && !url.startsWith("https://")) {
            throw new Error("Please provide an url that starts with http:// or https://");
        }
        this.url = url;
    }
    /**
     * Takes an Query object and executes it. Throws if error is encountered.
     */
    async execute(query, config) {
        const rpcResponse = await sendQuery(this.url, query, config !== null && config !== void 0 ? config : {});
        if (rpcResponse.error) {
            throw new RpcError(rpcResponse.error);
        }
        return rpcResponse.result;
    }
}
export class RpcError extends Error {
    constructor(errResponse) {
        super(errResponse.message);
        this.code = errResponse.code;
    }
}
//# sourceMappingURL=RpcDispatcher.js.map