UNPKG

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
"use strict"; 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;