UNPKG

@kiroboio/fct-core

Version:

Kirobo.io FCT Core library

136 lines 5.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getGasPrices = void 0; const ethers_1 = require("ethers"); var Network; (function (Network) { Network[Network["MAINNET"] = 1] = "MAINNET"; Network[Network["ARBITRUM"] = 42161] = "ARBITRUM"; Network[Network["BASE"] = 8453] = "BASE"; Network[Network["OPTIMISM"] = 10] = "OPTIMISM"; Network[Network["SEPOLIA"] = 11155111] = "SEPOLIA"; Network[Network["ARB_GOERLI"] = 421613] = "ARB_GOERLI"; })(Network || (Network = {})); const percentilesForNetworks = { [Network.MAINNET]: [1, 15, 35, 51], [Network.ARBITRUM]: [2, 5, 15, 25], [Network.OPTIMISM]: [2, 5, 15, 25], [Network.BASE]: [2, 5, 15, 25], // Testnets [Network.SEPOLIA]: [2, 10, 50, 80], [Network.ARB_GOERLI]: [2, 6, 15, 30], }; const getGasPrices = async ({ rpcUrl, chainId, historicalBlocks = 10, tries = 40, futureBlocks = 0, }) => { do { try { const { result, baseFee } = await getFeeHistory({ rpcUrl, chainId, historicalBlocks }); if (!result) { throw new Error("No result"); } const blocks = buildBlocks({ historicalBlocks, feeHistoryResult: result, oldestBlock: parseInt(result.oldestBlock, 16), }); return getGasPriceResult({ baseFee, chainId, averages: getAverages(blocks), futureBlocks }); } catch (err) { if (tries > 0) { // Wait 3 seconds before retrying await new Promise((resolve) => setTimeout(resolve, 3000)); } else { throw new Error("Could not get gas prices, issue might be related to node provider"); } } } while (tries-- > 0); throw new Error("Could not get gas prices, issue might be related to node provider"); }; exports.getGasPrices = getGasPrices; function avg(arr) { if (arr.every((v) => v === undefined)) { return 0n; } const sum = arr.reduce((a, v) => BigInt(a) + BigInt(v), 0n); return sum / BigInt(arr.length); } function getMaxBaseFeeInFutureBlock(baseFee, blocksInFuture) { let maxBaseFee = baseFee; for (let i = 0; i < blocksInFuture; i++) { maxBaseFee = (maxBaseFee * 1125n) / 1000n + 1n; } return maxBaseFee; } async function getFeeHistory({ rpcUrl, chainId, historicalBlocks, }) { const provider = new ethers_1.ethers.providers.JsonRpcProvider(rpcUrl); const latestBlock = await provider.getBlock("latest"); if (!latestBlock.baseFeePerGas) { throw new Error("No baseFeePerGas"); } const baseFee = latestBlock.baseFeePerGas.toString(); const blockNumber = latestBlock.number; const data = await fetchFeeHistory({ historicalBlocks, blockNumber, chainId, rpcUrl }); return { result: data.result, baseFee, }; } async function fetchFeeHistory({ historicalBlocks, blockNumber, chainId, rpcUrl, }) { const res = await fetch(rpcUrl, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ jsonrpc: "2.0", method: "eth_feeHistory", params: [ historicalBlocks, `0x${blockNumber.toString(16)}`, percentilesForNetworks[chainId] || percentilesForNetworks[1], ], id: 1, }), }); return (await res.json()); } function buildBlocks({ historicalBlocks, feeHistoryResult, oldestBlock, }) { let blockNum = oldestBlock; return Array.from({ length: historicalBlocks - 1 }, (_, i) => { const number = blockNum; blockNum += 1; return { number, baseFeePerGas: feeHistoryResult.baseFeePerGas[i], gasUsedRatio: feeHistoryResult.gasUsedRatio[i], priorityFeePerGas: feeHistoryResult.reward ? feeHistoryResult.reward[i] : [], }; }); } function getAverages(blocks) { return { slow: avg(blocks.map((b) => b.priorityFeePerGas[0])), average: avg(blocks.map((b) => b.priorityFeePerGas[1])), fast: avg(blocks.map((b) => b.priorityFeePerGas[2])), fastest: avg(blocks.map((b) => b.priorityFeePerGas[3])), }; } function getGasPriceResult({ baseFee, chainId, averages, futureBlocks, }) { const { slow, average, fast, fastest } = averages; // On Arbitrum use the baseFee as is, otherwise calculate the baseFee for 2 blocks in the future const baseFeePerGas = chainId === 42161 ? BigInt(baseFee) : getMaxBaseFeeInFutureBlock(BigInt(baseFee), futureBlocks); return { baseFee: baseFee, slow: gasPriceCalculation({ priorityFee: slow, baseFee: baseFeePerGas }), average: gasPriceCalculation({ priorityFee: average, baseFee: baseFeePerGas }), fast: gasPriceCalculation({ priorityFee: fast, baseFee: baseFeePerGas }), fastest: gasPriceCalculation({ priorityFee: fastest, baseFee: baseFeePerGas }), }; } function gasPriceCalculation({ priorityFee, baseFee }) { return { maxFeePerGas: (baseFee + priorityFee).toString(), maxPriorityFeePerGas: priorityFee.toString(), }; } //# sourceMappingURL=gas.js.map