import { __awaiter, __extends, __generator, __spreadArray } from "tslib";
import { ethers } from "ethers";
import { CacheProvider } from "./cachedProvider";
import { formatProviderError } from "./utils";
import { PROVIDER_CACHE_TTL } from "./constants";
/**
 * RPC provider that sends requests to multiple providers in parallel and returns the fastest response.
 */
var SpeedProvider = /** @class */ (function (_super) {
    __extends(SpeedProvider, _super);
    function SpeedProvider(params, chainId, maxConcurrencySpeed, maxConcurrencyRateLimit, providerCacheNamespace, pctRpcCallsLogged, redisClient, standardTtlBlockDistance, noTtlBlockDistance, providerCacheTtl, logger) {
        if (providerCacheTtl === void 0) { providerCacheTtl = PROVIDER_CACHE_TTL; }
        var _this = 
        // Initialize the super just with the chainId, which stops it from trying to immediately send out a .send before
        // this derived class is initialized.
        _super.call(this, undefined, chainId) || this;
        _this.maxConcurrencySpeed = maxConcurrencySpeed;
        _this.maxConcurrencyRateLimit = maxConcurrencyRateLimit;
        _this.providers = params.map(function (inputs) {
            return new (CacheProvider.bind.apply(CacheProvider, __spreadArray([void 0, providerCacheNamespace,
                redisClient,
                standardTtlBlockDistance,
                noTtlBlockDistance,
                providerCacheTtl,
                maxConcurrencyRateLimit,
                pctRpcCallsLogged,
                logger], inputs, false)))();
        });
        return _this;
    }
    SpeedProvider.prototype.send = function (method, params) {
        return __awaiter(this, void 0, void 0, function () {
            var providersToUse, result, error_1, errors;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        _a.trys.push([0, 2, , 3]);
                        providersToUse = this.providers.slice(0, this.maxConcurrencySpeed);
                        return [4 /*yield*/, Promise.any(providersToUse.map(function (provider) { return provider.send(method, params); }))];
                    case 1:
                        result = _a.sent();
                        return [2 /*return*/, result];
                    case 2:
                        error_1 = _a.sent();
                        // Only thrown if all providers failed to respond
                        if (error_1 instanceof AggregateError) {
                            errors = error_1.errors.map(function (error, index) {
                                var provider = _this.providers[index];
                                return formatProviderError(provider, error.message);
                            });
                            throw new Error("All providers errored:\n" + errors.join("\n"));
                        }
                        throw error_1;
                    case 3: return [2 /*return*/];
                }
            });
        });
    };
    return SpeedProvider;
}(ethers.providers.StaticJsonRpcProvider));
export { SpeedProvider };
//# sourceMappingURL=speedProvider.js.map