@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
JavaScript
;
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;