import { __assign, __awaiter, __generator } from "tslib";
import assert from "assert";
import { CHAIN_IDs } from "../constants";
import { BigNumber, fixedPointAdjustment, isEvmProvider, toBNWei, isDefined } from "../utils";
import { getPublicClient } from "./util";
import * as arbitrum from "./adapters/arbitrum";
import * as ethereum from "./adapters/ethereum";
import * as polygon from "./adapters/polygon";
import * as lineaViem from "./adapters/linea-viem";
import * as solana from "./adapters/solana";
var GAS_PRICE_ESTIMATE_DEFAULTS = {
    legacyFallback: true,
};
// Chains that use the Viem gas price oracle.
var VIEM_CHAINS = [CHAIN_IDs.LINEA];
/**
 * Provide an estimate for the current gas price for a particular chain.
 * @param provider A valid ethers provider.
 * @param {GasPriceEstimateOptions} opts optional parameters.
 * @returns An  object of type GasPriceEstimate.
 */
export function getGasPriceEstimate(provider_1) {
    return __awaiter(this, arguments, void 0, function (provider, opts) {
        var baseFeeMultiplier, priorityFeeMultiplier, optsWithDefaults_1, chainId, _a, optsWithDefaults, useViem;
        var _b, _c, _d, _e;
        if (opts === void 0) { opts = {}; }
        return __generator(this, function (_f) {
            switch (_f.label) {
                case 0:
                    baseFeeMultiplier = (_b = opts.baseFeeMultiplier) !== null && _b !== void 0 ? _b : toBNWei("1");
                    priorityFeeMultiplier = (_c = opts.priorityFeeMultiplier) !== null && _c !== void 0 ? _c : toBNWei("1");
                    // Exit here if we need to estimate on Solana.
                    if (!isEvmProvider(provider)) {
                        optsWithDefaults_1 = __assign(__assign(__assign(__assign({}, GAS_PRICE_ESTIMATE_DEFAULTS), { baseFeeMultiplier: baseFeeMultiplier, priorityFeeMultiplier: priorityFeeMultiplier }), opts), { chainId: (_d = opts.chainId) !== null && _d !== void 0 ? _d : CHAIN_IDs.SOLANA });
                        return [2 /*return*/, solana.messageFee(provider, optsWithDefaults_1)];
                    }
                    if (!((_e = opts.chainId) !== null && _e !== void 0)) return [3 /*break*/, 1];
                    _a = _e;
                    return [3 /*break*/, 3];
                case 1: return [4 /*yield*/, provider.getNetwork()];
                case 2:
                    _a = (_f.sent()).chainId;
                    _f.label = 3;
                case 3:
                    chainId = _a;
                    optsWithDefaults = __assign(__assign(__assign(__assign({}, GAS_PRICE_ESTIMATE_DEFAULTS), { baseFeeMultiplier: baseFeeMultiplier, priorityFeeMultiplier: priorityFeeMultiplier }), opts), { chainId: chainId });
                    useViem = VIEM_CHAINS.includes(chainId);
                    return [2 /*return*/, useViem ? getGasPriceViem(chainId, optsWithDefaults) : getGasPriceEthers(provider, optsWithDefaults)];
            }
        });
    });
}
/**
 * Provide an estimate for the current gas price for a particular chain.
 * @param chainId The chain ID to query for gas prices.
 * @param provider A valid ethers provider.
 * @param legacyFallback In the case of an unrecognised chain, fall back to type 0 gas estimation.
 * @returns An object of type GasPriceEstimate.
 */
function getGasPriceEthers(provider, opts) {
    var _a;
    var chainId = opts.chainId, legacyFallback = opts.legacyFallback;
    // There shouldn't be any chains in here that we have a Viem adapter for because we'll always use Viem in that case.
    assert(!VIEM_CHAINS.includes(chainId), "Chain ID ".concat(chainId, " will use Viem gas price estimation"));
    var gasPriceFeeds = (_a = {},
        _a[CHAIN_IDs.ARBITRUM] = arbitrum.eip1559,
        _a[CHAIN_IDs.POLYGON] = polygon.gasStation,
        _a[CHAIN_IDs.SCROLL] = ethereum.legacy,
        _a[CHAIN_IDs.TEMPO] = ethereum.eip1559,
        _a[CHAIN_IDs.ZK_SYNC] = ethereum.legacy,
        // Testnet
        _a[CHAIN_IDs.POLYGON_AMOY] = polygon.gasStation,
        _a);
    // If we have specified feeHistory parameters, then assume we want to take the feeHistory estimation path.
    var gasPriceFeed = isDefined(opts.feeHistoryOptions) ? ethereum.feeHistory : gasPriceFeeds[chainId];
    assert(gasPriceFeed || legacyFallback, "No suitable gas price oracle for Chain ID ".concat(chainId));
    gasPriceFeed !== null && gasPriceFeed !== void 0 ? gasPriceFeed : (gasPriceFeed = ethereum.eip1559);
    return gasPriceFeed(provider, opts);
}
/**
 * Provide an estimate for the current gas price for a particular chain.
 * @param providerOrChainId A valid ethers provider or a chain ID.
 * @param transport An optional Viem Transport object for custom gas price retrieval.
 * @param unsignedTx Only used in Linea provider to estimate priority gas fee.
 * @returns An object of type GasPriceEstimate.
 */
function getGasPriceViem(chainId, opts) {
    return __awaiter(this, void 0, void 0, function () {
        var baseFeeMultiplier, transport, viemProvider, gasPriceFeeds, maxFeePerGas, maxPriorityFeePerGas, gasPrice;
        var _a, _b, _c;
        return __generator(this, function (_d) {
            switch (_d.label) {
                case 0:
                    baseFeeMultiplier = opts.baseFeeMultiplier, transport = opts.transport;
                    viemProvider = getPublicClient(chainId, transport);
                    gasPriceFeeds = (_a = {},
                        _a[CHAIN_IDs.LINEA] = lineaViem.eip1559,
                        _a);
                    if (!gasPriceFeeds[chainId]) return [3 /*break*/, 2];
                    return [4 /*yield*/, gasPriceFeeds[chainId](viemProvider, opts)];
                case 1:
                    (_b = _d.sent(), maxFeePerGas = _b.maxFeePerGas, maxPriorityFeePerGas = _b.maxPriorityFeePerGas);
                    return [3 /*break*/, 4];
                case 2:
                    gasPrice = void 0;
                    return [4 /*yield*/, viemProvider.estimateFeesPerGas()];
                case 3:
                    (_c = _d.sent(), maxFeePerGas = _c.maxFeePerGas, maxPriorityFeePerGas = _c.maxPriorityFeePerGas, gasPrice = _c.gasPrice);
                    maxFeePerGas !== null && maxFeePerGas !== void 0 ? maxFeePerGas : (maxFeePerGas = (gasPrice * BigInt(baseFeeMultiplier.toString())) / BigInt(fixedPointAdjustment.toString()));
                    maxPriorityFeePerGas !== null && maxPriorityFeePerGas !== void 0 ? maxPriorityFeePerGas : (maxPriorityFeePerGas = BigInt(0));
                    _d.label = 4;
                case 4: return [2 /*return*/, {
                        maxFeePerGas: BigNumber.from(maxFeePerGas.toString()),
                        maxPriorityFeePerGas: BigNumber.from(maxPriorityFeePerGas.toString()),
                    }];
            }
        });
    });
}
//# sourceMappingURL=oracle.js.map