"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RateLimitedSolanaRpcFactory = void 0;
const tslib_1 = require("tslib");
const async_1 = require("async");
const winston_1 = tslib_1.__importDefault(require("winston"));
const baseRpcFactories_1 = require("./baseRpcFactories");
const defaultRpcFactory_1 = require("./defaultRpcFactory");
const utils_1 = require("../../utils");
class RateLimitedSolanaRpcFactory extends baseRpcFactories_1.SolanaClusterRpcFactory {
    pctRpcCallsLogged;
    logger;
    queue;
    defaultTransport;
    constructor(maxConcurrency, pctRpcCallsLogged, logger = winston_1.default.createLogger({
        transports: [new winston_1.default.transports.Console()],
    }), ...defaultConstructorParams) {
        super(...defaultConstructorParams);
        this.pctRpcCallsLogged = pctRpcCallsLogged;
        this.logger = logger;
        this.defaultTransport = new defaultRpcFactory_1.SolanaDefaultRpcFactory(...defaultConstructorParams).createTransport();
        this.queue = (0, async_1.queue)(async ({ rpcArgs, resolve, reject }, callback) => {
            await this.wrapSendWithLog(...rpcArgs)
                .then(resolve)
                .catch(reject);
            callback();
        }, maxConcurrency);
    }
    async wrapSendWithLog(...rpcArgs) {
        if (this.pctRpcCallsLogged <= 0 || Math.random() > this.pctRpcCallsLogged / 100) {
            return await this.defaultTransport(...rpcArgs);
        }
        else {
            const payload = rpcArgs[0].payload;
            const loggerArgs = {
                at: "SolanaProviderUtils",
                message: "Solana provider response sample",
                provider: (0, utils_1.getOriginFromURL)(this.clusterUrl),
                method: payload.method,
                params: payload.params,
                chainId: this.chainId,
                datadog: true,
            };
            const startTime = performance.now();
            try {
                const result = await this.defaultTransport(...rpcArgs);
                const elapsedTimeS = (performance.now() - startTime) / 1000;
                this.logger.debug({
                    ...loggerArgs,
                    success: true,
                    timeElapsed: elapsedTimeS,
                });
                return result;
            }
            catch (error) {
                const elapsedTimeS = (performance.now() - startTime) / 1000;
                this.logger.debug({
                    ...loggerArgs,
                    success: false,
                    timeElapsed: elapsedTimeS,
                });
                throw error;
            }
        }
    }
    createTransport() {
        return (...args) => {
            return new Promise((resolve, reject) => {
                const task = {
                    rpcArgs: args,
                    resolve: resolve,
                    reject,
                };
                void this.queue.push(task);
            });
        };
    }
}
exports.RateLimitedSolanaRpcFactory = RateLimitedSolanaRpcFactory;
//# sourceMappingURL=rateLimitedRpcFactory.js.map