UNPKG

@rainbow-me/fee-suggestions

Version:

JavaScript library that suggest fees on Ethereum after EIP-1559 using historical data using ethers.js

190 lines (189 loc) 7.07 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateBaseFeeTrend = exports.getData = exports.rewardsFilterOutliers = exports.getOutlierBlocksToRemove = exports.suggestBaseFee = exports.linearRegression = exports.samplingCurve = exports.weiToString = exports.weiToGweiNumber = exports.weiToGwei = exports.gweiToWei = exports.divide = exports.multiply = void 0; var bignumber_js_1 = __importDefault(require("bignumber.js")); var constants_1 = require("./constants"); var ethUnits = { gwei: 1000000000, }; var FALLING = constants_1.TREND_THRESHOLDS.FALLING, MEDIAN_SLOPE = constants_1.TREND_THRESHOLDS.MEDIAN_SLOPE, RAISING = constants_1.TREND_THRESHOLDS.RAISING, SURGING = constants_1.TREND_THRESHOLDS.SURGING; var multiply = function (numberOne, numberTwo) { return new bignumber_js_1.default(numberOne).times(numberTwo); }; exports.multiply = multiply; var divide = function (numberOne, numberTwo) { if (!(numberOne || numberTwo)) return new bignumber_js_1.default(0); return new bignumber_js_1.default(numberOne).dividedBy(numberTwo); }; exports.divide = divide; var gweiToWei = function (gweiAmount) { var weiAmount = (0, exports.multiply)(gweiAmount, ethUnits.gwei).toFixed(0); return weiAmount; }; exports.gweiToWei = gweiToWei; var weiToGwei = function (weiAmount) { var gweiAmount = (0, exports.divide)(weiAmount, ethUnits.gwei).toFixed(); return gweiAmount; }; exports.weiToGwei = weiToGwei; var weiToGweiNumber = function (weiAmount) { var gweiAmount = (0, exports.divide)(weiAmount, ethUnits.gwei).toNumber(); return gweiAmount; }; exports.weiToGweiNumber = weiToGweiNumber; var weiToString = function (weiAmount) { return new bignumber_js_1.default(weiAmount).toString(); }; exports.weiToString = weiToString; var samplingCurve = function (sumWeight, sampleMin, sampleMax) { if (sumWeight <= sampleMin) { return 0; } if (sumWeight >= sampleMax) { return 1; } return ((1 - Math.cos(((sumWeight - sampleMin) * 2 * Math.PI) / (sampleMax - sampleMin))) / 2); }; exports.samplingCurve = samplingCurve; var linearRegression = function (y) { var x = Array.from(Array(y.length + 1).keys()); var n = y.length; var sumX = 0; var sumY = 0; var sumXY = 0; var sumXX = 0; for (var i = 0; i < y.length; i++) { var cY = Number(y[i]); var cX = Number(x[i]); sumX += cX; sumY += cY; sumXY += cX * cY; sumXX += cX * cX; } var slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX); return slope; }; exports.linearRegression = linearRegression; var suggestBaseFee = function (baseFee, order, timeFactor, sampleMin, sampleMax) { if (timeFactor < 1e-6) { return baseFee[baseFee.length - 1]; } var pendingWeight = (1 - Math.exp(-1 / timeFactor)) / (1 - Math.exp(-baseFee.length / timeFactor)); var sumWeight = 0; var result = 0; var samplingCurveLast = 0; for (var _i = 0, order_1 = order; _i < order_1.length; _i++) { var or = order_1[_i]; sumWeight += pendingWeight * Math.exp((or - baseFee.length + 1) / timeFactor); var samplingCurveValue = (0, exports.samplingCurve)(sumWeight, sampleMin, sampleMax); result += (samplingCurveValue - samplingCurveLast) * baseFee[or]; if (samplingCurveValue >= 1) { return result; } samplingCurveLast = samplingCurveValue; } return result; }; exports.suggestBaseFee = suggestBaseFee; var getOutlierBlocksToRemove = function (blocksRewards, index) { var blocks = []; blocksRewards .map(function (reward) { return (0, exports.weiToGweiNumber)(reward[index]); }) .forEach(function (gweiReward, i) { if (gweiReward > 5) { blocks.push(i); } }); return blocks; }; exports.getOutlierBlocksToRemove = getOutlierBlocksToRemove; var rewardsFilterOutliers = function (blocksRewards, outlierBlocks, rewardIndex) { return blocksRewards .filter(function (_, index) { return !outlierBlocks.includes(index); }) .map(function (reward) { return (0, exports.weiToGweiNumber)(reward[rewardIndex]); }); }; exports.rewardsFilterOutliers = rewardsFilterOutliers; var calculateGroupInfo = function (baseFees) { var sortedBaseFees = baseFees.sort(function (a, b) { return a - b; }); var min = sortedBaseFees[0]; var max = sortedBaseFees[sortedBaseFees.length - 1]; var median = sortedBaseFees[Math.floor(sortedBaseFees.length / 2)]; return { max: max, median: median, min: min }; }; var createSubsets = function (numbers, n) { var subsets = []; for (var i = 0; i < numbers.length; i = i + n) { subsets.push(numbers.slice(i, i + n)); } return subsets; }; var getData = function (numbers, n) { var subsets = createSubsets(numbers, n); var subsetsInfo = subsets.map(function (subset) { return calculateGroupInfo(subset); }); var _a = subsetsInfo[subsetsInfo.length - 1], lastMax = _a.max, lastMin = _a.min, lastMedian = _a.median; var medianData = subsetsInfo.map(function (data) { return data.median; }); var medianSlope = (0, exports.linearRegression)(medianData); return { max: lastMax, median: lastMedian, medianSlope: medianSlope, min: lastMin, }; }; exports.getData = getData; var calculateBaseFeeTrend = function (baseFees, currentBaseFee) { var trend = 0; try { // taking 50 blocks var baseFees50Blocks = baseFees.slice(51); // divide it in groups of 5 var n50 = { g5: (0, exports.getData)(baseFees50Blocks, 5), }; // taking 100 blocks var baseFees100Blocks = baseFees.slice(1); // divide it in groups of 25 var n100 = { g25: (0, exports.getData)(baseFees100Blocks, 25), }; var maxByMedian = n100.g25.max / n100.g25.median; var minByMedian = n100.g25.min / n100.g25.median; if (maxByMedian > SURGING) { trend = 2; } else if (maxByMedian > RAISING && minByMedian > FALLING) { trend = 1; } else if (maxByMedian < RAISING && minByMedian > FALLING) { if (n50.g5.medianSlope < MEDIAN_SLOPE) { trend = -1; } else { trend = 0; } } else if (maxByMedian < RAISING && minByMedian < FALLING) { trend = -1; } else { // if none is on the threshold if ((0, exports.weiToGweiNumber)(currentBaseFee) > n100.g25.median) { trend = 1; } else { trend = -1; } } } catch (e) { // } return trend; }; exports.calculateBaseFeeTrend = calculateBaseFeeTrend;