ethers-maths
Version:
➗ Useful ethers-based math libraries to ease the journey through off-chain fixed-point arithmetics
119 lines (118 loc) • 4.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getConvertToShares = exports.getConvertToAssets = exports.expN = exports.pow = exports.avgHalfUp = exports.mulDivUp = exports.mulDivDown = exports.mulDivHalfUp = exports.sum = exports.max = exports.min = exports.abs = exports.approxEqAbs = exports.pow10 = void 0;
const ethers_1 = require("ethers");
const pow10 = (power) => (0, ethers_1.toBigInt)(10) ** (0, ethers_1.toBigInt)(power);
exports.pow10 = pow10;
const approxEqAbs = (x, y, tolerance = 0) => {
x = (0, ethers_1.toBigInt)(x);
y = (0, ethers_1.toBigInt)(y);
tolerance = (0, ethers_1.toBigInt)(tolerance);
return (0, exports.abs)(y - x) <= tolerance;
};
exports.approxEqAbs = approxEqAbs;
const abs = (x) => {
x = (0, ethers_1.toBigInt)(x);
return x < 0n ? -x : x;
};
exports.abs = abs;
const min = (x, ...others) => {
x = (0, ethers_1.toBigInt)(x);
if (others.length === 0)
return x;
const y = (0, ethers_1.toBigInt)(others[0]);
return (0, exports.min)(x > y ? y : x, ...others.slice(1));
};
exports.min = min;
const max = (x, ...others) => {
x = (0, ethers_1.toBigInt)(x);
if (others.length === 0)
return x;
const y = (0, ethers_1.toBigInt)(others[0]);
return (0, exports.max)(x > y ? x : y, ...others.slice(1));
};
exports.max = max;
const sum = (initialValue, others) => {
return others.reduce((acc, val) => acc + (0, ethers_1.toBigInt)(val), (0, ethers_1.toBigInt)(initialValue));
};
exports.sum = sum;
const mulDivHalfUp = (x, y, scale) => {
x = (0, ethers_1.toBigInt)(x);
y = (0, ethers_1.toBigInt)(y);
scale = (0, ethers_1.toBigInt)(scale);
if (x === 0n || y === 0n)
return (0, ethers_1.toBigInt)(0);
return (x * y + scale / 2n) / scale;
};
exports.mulDivHalfUp = mulDivHalfUp;
const mulDivDown = (x, y, scale) => {
x = (0, ethers_1.toBigInt)(x);
y = (0, ethers_1.toBigInt)(y);
scale = (0, ethers_1.toBigInt)(scale);
if (x === 0n || y === 0n)
return (0, ethers_1.toBigInt)(0);
return (x * y) / scale;
};
exports.mulDivDown = mulDivDown;
const mulDivUp = (x, y, scale) => {
x = (0, ethers_1.toBigInt)(x);
y = (0, ethers_1.toBigInt)(y);
scale = (0, ethers_1.toBigInt)(scale);
if (x === 0n || y === 0n)
return (0, ethers_1.toBigInt)(0);
return (x * y + scale - 1n) / scale;
};
exports.mulDivUp = mulDivUp;
const avgHalfUp = (x, y, pct, scale) => {
x = (0, ethers_1.toBigInt)(x);
y = (0, ethers_1.toBigInt)(y);
pct = (0, ethers_1.toBigInt)(pct);
scale = (0, ethers_1.toBigInt)(scale);
return ((0, exports.max)(0, scale - pct) * x + (0, exports.min)(scale, pct) * y + scale / 2n) / scale;
};
exports.avgHalfUp = avgHalfUp;
const pow = (x, exponent, scale, mulDiv = exports.mulDivHalfUp) => {
exponent = (0, ethers_1.toBigInt)(exponent);
if (exponent === 0n)
return (0, ethers_1.toBigInt)(scale);
if (exponent === 1n)
return (0, ethers_1.toBigInt)(x);
const xSquared = mulDiv(x, x, scale);
if (exponent % 2n === 0n)
return (0, exports.pow)(xSquared, exponent / 2n, scale, mulDiv);
return mulDiv(x, (0, exports.pow)(xSquared, (exponent - 1n) / 2n, scale, mulDiv), scale);
};
exports.pow = pow;
const expN = (x, N, scale, mulDiv = exports.mulDivDown) => {
x = (0, ethers_1.toBigInt)(x);
scale = (0, ethers_1.toBigInt)(scale);
N = (0, ethers_1.toBigInt)(N);
let res = scale;
let monomial = scale;
for (let k = (0, ethers_1.toBigInt)(1); k <= N; k++) {
monomial = mulDiv(monomial, x, k * scale);
res += monomial;
}
return res;
};
exports.expN = expN;
const getConvertToAssets = (virtualAssets, virtualShares, mulDiv) => {
virtualAssets = (0, ethers_1.toBigInt)(virtualAssets);
virtualShares = (0, ethers_1.toBigInt)(virtualShares);
return (shares, totalAssets, totalShares) => {
totalAssets = (0, ethers_1.toBigInt)(totalAssets);
totalShares = (0, ethers_1.toBigInt)(totalShares);
return mulDiv(shares, totalAssets + virtualAssets, totalShares + virtualShares);
};
};
exports.getConvertToAssets = getConvertToAssets;
const getConvertToShares = (virtualAssets, virtualShares, mulDiv) => {
virtualAssets = (0, ethers_1.toBigInt)(virtualAssets);
virtualShares = (0, ethers_1.toBigInt)(virtualShares);
return (assets, totalAssets, totalShares) => {
totalAssets = (0, ethers_1.toBigInt)(totalAssets);
totalShares = (0, ethers_1.toBigInt)(totalShares);
return mulDiv(assets, totalShares + virtualShares, totalAssets + virtualAssets);
};
};
exports.getConvertToShares = getConvertToShares;