"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RateLimitedProvider = void 0;
var tslib_1 = require("tslib");
var async_1 = require("async");
var ethers_1 = require("ethers");
var NetworkUtils_1 = require("../utils/NetworkUtils");
var winston_1 = tslib_1.__importDefault(require("winston"));
var RateLimitedProvider = (function (_super) {
    tslib_1.__extends(RateLimitedProvider, _super);
    function RateLimitedProvider(maxConcurrency, pctRpcCallsLogged, logger) {
        if (logger === void 0) { logger = winston_1.default.createLogger({
            transports: [new winston_1.default.transports.Console()],
        }); }
        var cacheConstructorParams = [];
        for (var _i = 3; _i < arguments.length; _i++) {
            cacheConstructorParams[_i - 3] = arguments[_i];
        }
        var _this = _super.apply(this, cacheConstructorParams) || this;
        _this.pctRpcCallsLogged = pctRpcCallsLogged;
        _this.logger = logger;
        _this.queue = (0, async_1.queue)(function (_a, callback) {
            var sendArgs = _a.sendArgs, resolve = _a.resolve, reject = _a.reject;
            return tslib_1.__awaiter(_this, void 0, void 0, function () {
                return tslib_1.__generator(this, function (_b) {
                    switch (_b.label) {
                        case 0: return [4, this.wrapSendWithLog.apply(this, sendArgs).then(resolve)
                                .catch(reject)];
                        case 1:
                            _b.sent();
                            callback();
                            return [2];
                    }
                });
            });
        }, maxConcurrency);
        return _this;
    }
    RateLimitedProvider.prototype.wrapSendWithLog = function (method, params) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var loggerArgs, startTime, result, elapsedTimeS, error_1, elapsedTimeS;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!(this.pctRpcCallsLogged <= 0 || Math.random() > this.pctRpcCallsLogged / 100)) return [3, 1];
                        return [2, _super.prototype.send.call(this, method, params)];
                    case 1:
                        loggerArgs = {
                            at: "ProviderUtils",
                            message: "Provider response sample",
                            provider: (0, NetworkUtils_1.getOriginFromURL)(this.connection.url),
                            method: method,
                            params: params,
                            chainId: this.network.chainId,
                            datadog: true,
                        };
                        startTime = performance.now();
                        _a.label = 2;
                    case 2:
                        _a.trys.push([2, 4, , 5]);
                        return [4, _super.prototype.send.call(this, method, params)];
                    case 3:
                        result = _a.sent();
                        elapsedTimeS = (performance.now() - startTime) / 1000;
                        this.logger.debug(tslib_1.__assign(tslib_1.__assign({}, loggerArgs), { success: true, timeElapsed: elapsedTimeS }));
                        return [2, result];
                    case 4:
                        error_1 = _a.sent();
                        elapsedTimeS = (performance.now() - startTime) / 1000;
                        this.logger.debug(tslib_1.__assign(tslib_1.__assign({}, loggerArgs), { success: false, timeElapsed: elapsedTimeS }));
                        throw error_1;
                    case 5: return [2];
                }
            });
        });
    };
    RateLimitedProvider.prototype.send = function (method, params) {
        var _this = this;
        return new Promise(function (resolve, reject) {
            var task = {
                sendArgs: [method, params],
                resolve: resolve,
                reject: reject,
            };
            void _this.queue.push(task);
        });
    };
    return RateLimitedProvider;
}(ethers_1.ethers.providers.StaticJsonRpcProvider));
exports.RateLimitedProvider = RateLimitedProvider;
//# sourceMappingURL=rateLimitedProvider.js.map