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.
 */
export class SpeedProvider extends ethers.providers.StaticJsonRpcProvider {
    maxConcurrencySpeed;
    maxConcurrencyRateLimit;
    providers;
    constructor(params, chainId, maxConcurrencySpeed, maxConcurrencyRateLimit, providerCacheNamespace, pctRpcCallsLogged, redisClient, standardTtlBlockDistance, noTtlBlockDistance, providerCacheTtl = PROVIDER_CACHE_TTL, logger) {
        // 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(undefined, chainId);
        this.maxConcurrencySpeed = maxConcurrencySpeed;
        this.maxConcurrencyRateLimit = maxConcurrencyRateLimit;
        this.providers = params.map((inputs) => new CacheProvider(providerCacheNamespace, redisClient, standardTtlBlockDistance, noTtlBlockDistance, providerCacheTtl, maxConcurrencyRateLimit, pctRpcCallsLogged, logger, ...inputs));
    }
    async send(method, params) {
        try {
            const providersToUse = this.providers.slice(0, this.maxConcurrencySpeed);
            const result = await Promise.any(providersToUse.map((provider) => provider.send(method, params)));
            return result;
        }
        catch (error) {
            // Only thrown if all providers failed to respond
            if (error instanceof AggregateError) {
                const errors = error.errors.map((error, index) => {
                    const provider = this.providers[index];
                    return formatProviderError(provider, error.message);
                });
                throw new Error("All providers errored:\n" + errors.join("\n"));
            }
            throw error;
        }
    }
}
//# sourceMappingURL=speedProvider.js.map