From ad89d52e2dc74d0dd039917ba1bc8176c59eee82 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Fri, 29 Sep 2023 15:12:51 +0200 Subject: [PATCH] feat(lib): extract utils to scale-specific domains BREAKING CHANGE: function names changes --- README.md | 36 ++++---- src/comp.ts | 10 +++ src/format.ts | 32 ++++++++ src/index.ts | 219 ++++++++++++++++++++++++++++--------------------- src/percent.ts | 78 ++++++++++++++++++ src/ray.ts | 78 ++++++++++++++++++ src/utils.ts | 6 +- src/wad.ts | 78 ++++++++++++++++++ 8 files changed, 424 insertions(+), 113 deletions(-) create mode 100644 src/comp.ts create mode 100644 src/format.ts create mode 100644 src/percent.ts create mode 100644 src/ray.ts create mode 100644 src/wad.ts diff --git a/README.md b/README.md index 73cefde..546a56e 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,14 @@ BigInt.from(1).wadMul(WAD); // 1 BigInt.from(WAD * 2n).rayMul(0.5e27); // WAD ``` +If you choose to avoid prototype pollution, you can always import specific utilities: + +```typescript +import * as WadMath from "ethers-maths/lib/wad"; +import * as RayMath from "ethers-maths/lib/ray"; +import * as PercentMath from "ethers-maths/lib/percent"; +``` + --- ## Book @@ -125,7 +133,7 @@ Returns whether the BigNumber is approximately close to the given BigNumber, wit ```typescript // only if you want to avoid BigNumber prototype pollution -import { approxEqAbs } from "ethers-maths/utils"; +import { approxEqAbs } from "ethers-maths/lib/utils"; // Returns whether the BigNumber is approximately close to the given BigNumber, within the given tolerance: true approxEqAbs(0, 1, "1"); @@ -139,7 +147,7 @@ Returns the minimum between input BigNumberish, as a BigInt ```typescript // only if you want to avoid BigInt prototype pollution -import { min } from "ethers-maths/utils"; +import { min } from "ethers-maths/lib/utils"; // Returns the minimum between input BigNumberish, as a BigInt: 0 min(0, 1, "2", ...); @@ -153,7 +161,7 @@ Returns the maximum between input BigNumberish, as a BigInt ```typescript // only if you want to avoid BigInt prototype pollution -import { max } from "ethers-maths/utils"; +import { max } from "ethers-maths/lib/utils"; // Returns the maximum between input BigNumberish, as a BigInt: 2 max(0, 1, "2", ...); @@ -167,7 +175,7 @@ Returns the sum of input BigNumberish array, as a BigInt ```typescript // only if you want to avoid BigInt prototype pollution -import { sum } from "ethers-maths/utils"; +import { sum } from "ethers-maths/lib/utils"; // Returns the sum of input BigNumberish array, as a BigInt: 3 sum([0, 1, "2"]); @@ -204,7 +212,7 @@ Returns a 1 followed by the input number of zeros (10 raised to the power of the ```typescript // only if you want to avoid BigInt prototype pollution -import { pow10 } from "ethers-maths/utils"; +import { pow10 } from "ethers-maths/lib/utils"; // Returns a 1 followed by the input number of zeros: 100 pow10(2); @@ -217,7 +225,7 @@ Performs a multiplication followed by a division, rounded half up ```typescript // only if you want to avoid BigInt prototype pollution -import { mulDivHalfUp } from "ethers-maths/utils"; +import { mulDivHalfUp } from "ethers-maths/lib/utils"; // 1.0 (in wad) * 1 / 1 = 1.0 (in wad) mulDivHalfUp(BigInt.WAD, 1, 1); @@ -230,7 +238,7 @@ Performs a multiplication followed by a division, rounded up ```typescript // only if you want to avoid BigInt prototype pollution -import { mulDivUp } from "ethers-maths/utils"; +import { mulDivUp } from "ethers-maths/lib/utils"; // 0.999999999999999999 * 1 / WAD = 1.0 (in wad, rounded up) mulDivUp(BigInt.WAD - 1n, 1, BigInt.WAD); @@ -243,7 +251,7 @@ Performs a multiplication followed by a division, rounded down ```typescript // only if you want to avoid BigInt prototype pollution -import { mulDivDown } from "ethers-maths/utils"; +import { mulDivDown } from "ethers-maths/lib/utils"; // 1.000000000000000001 * 1 / WAD = 1.0 (in wad, rounded down) mulDivDown(BigInt.WAD + 1n, 1, BigInt.WAD); @@ -262,7 +270,7 @@ _Most commonly used as the ERC20 token unit_ ```typescript // only if you want to avoid BigInt prototype pollution -import { WAD } from "ethers-maths/constants"; +import { WAD } from "ethers-maths/lib/constants"; // Returns a 1 followed by 18 zeros: 1000000000000000000 WAD; @@ -277,7 +285,7 @@ _Most commonly used as Aave's index unit_ ```typescript // only if you want to avoid BigInt prototype pollution -import { RAY } from "ethers-maths/constants"; +import { RAY } from "ethers-maths/lib/constants"; // Returns a 1 followed by 27 zeros: 1000000000000000000000000000 RAY; @@ -292,7 +300,7 @@ _Most commonly used as Aave's `PERCENTAGE_FACTOR`_ ```typescript // only if you want to avoid BigInt prototype pollution -import { PERCENT } from "ethers-maths/constants"; +import { PERCENT } from "ethers-maths/lib/constants"; // Returns a 1 followed by 4 zeros: 10000 PERCENT; @@ -305,7 +313,7 @@ Returns half of the common WAD unit, which is also known as `0.5 ether` in Solid ```typescript // only if you want to avoid BigInt prototype pollution -import { HALF_WAD } from "ethers-maths/constants"; +import { HALF_WAD } from "ethers-maths/lib/constants"; // Returns a 1 followed by 18 zeros: 1000000000000000000 HALF_WAD; @@ -318,7 +326,7 @@ Returns half of the common RAY unit, which is also known as `0.5e9 ether` in Sol ```typescript // only if you want to avoid BigInt prototype pollution -import { HALF_RAY } from "ethers-maths/constants"; +import { HALF_RAY } from "ethers-maths/lib/constants"; // Returns a 1 followed by 27 zeros: 1000000000000000000000000000 HALF_RAY; @@ -333,7 +341,7 @@ _Most commonly used as Aave's `HALF_PERCENTAGE_FACTOR`_ ```typescript // only if you want to avoid BigInt prototype pollution -import { HALF_PERCENT } from "ethers-maths/constants"; +import { HALF_PERCENT } from "ethers-maths/lib/constants"; // Returns a 1 followed by 4 zeros: 10000 HALF_PERCENT; diff --git a/src/comp.ts b/src/comp.ts new file mode 100644 index 0000000..77e1787 --- /dev/null +++ b/src/comp.ts @@ -0,0 +1,10 @@ +import { BigNumberish, toBigInt } from "ethers"; +import { WAD, WAD_SQUARED } from "./constants"; + +export const compMul = (x: BigNumberish, other: BigNumberish) => { + return (toBigInt(x) * toBigInt(other)) / WAD; +}; + +export const compDiv = (x: BigNumberish, other: BigNumberish) => { + return (toBigInt(x) * WAD_SQUARED) / toBigInt(other) / WAD; +}; diff --git a/src/format.ts b/src/format.ts new file mode 100644 index 0000000..eda4284 --- /dev/null +++ b/src/format.ts @@ -0,0 +1,32 @@ +import { BigNumberish, formatUnits, toBigInt } from "ethers"; +import { pow10 } from "./utils"; + +export const format = (x: BigNumberish, decimals?: number, digits?: number) => { + const formatted = formatUnits(x, decimals); + + let dotIndex = formatted.indexOf("."); + if (dotIndex < 0) dotIndex = formatted.length; + + decimals = formatted.length - 1 - dotIndex; + digits ??= decimals; + + return digits < decimals + ? formatted.slice(0, dotIndex + (digits > 0 ? digits + 1 : 0)) + : formatted + "0".repeat(digits - decimals); +}; + +export const toFloat = (x: BigNumberish, decimals?: number) => { + return parseFloat(format(x, decimals)); +}; + +export const toDecimals = (x: BigNumberish, decimals: number, scaleDecimals: number) => { + x = toBigInt(x); + + if (decimals <= scaleDecimals) { + const ratio = pow10(scaleDecimals - decimals); + + return (x + ratio / 2n) / ratio; + } + + return x * pow10(decimals - scaleDecimals); +}; diff --git a/src/index.ts b/src/index.ts index ab62b57..8be1418 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,23 +1,82 @@ -import { BigNumberish, formatUnits, toBigInt } from "ethers"; +import { BigNumberish } from "ethers"; -import { PERCENT, RAY, HALF_PERCENT, HALF_RAY, HALF_WAD, WAD, WAD_SQUARED } from "./constants"; +import { PERCENT, RAY, HALF_PERCENT, HALF_RAY, HALF_WAD, WAD } from "./constants"; import { - avgHalfUp, max, min, sum, pow10, mulDivHalfUp, - parsePercent, - parseRay, - parseWad, - pow, mulDivUp, mulDivDown, approxEqAbs, abs, - expN, } from "./utils"; +import { format, toFloat } from "./format"; +import { compDiv, compMul } from "./comp"; +import { + parsePercent, + formatPercent, + percentAdd, + percentAvg, + percentDiv, + percentDivDown, + percentDivUp, + percentExpN, + percentMul, + percentMulDown, + percentMulUp, + percentPow, + percentPowDown, + percentPowUp, + percentSub, + percentToDecimals, + percentToRay, + percentToWad, + toPercentFloat, +} from "./percent"; +import { + parseWad, + formatWad, + wadAdd, + wadAvg, + wadDiv, + wadDivDown, + wadDivUp, + wadExpN, + wadMul, + wadMulDown, + wadMulUp, + wadPow, + wadPowDown, + wadPowUp, + wadSub, + wadToDecimals, + wadToRay, + wadToPercent, + toWadFloat, +} from "./wad"; +import { + parseRay, + formatRay, + rayAdd, + rayAvg, + rayDiv, + rayDivDown, + rayDivUp, + rayExpN, + rayMul, + rayMulDown, + rayMulUp, + rayPow, + rayPowDown, + rayPowUp, + raySub, + rayToDecimals, + rayToWad, + rayToPercent, + toRayFloat, +} from "./ray"; declare global { interface BigInt { @@ -129,20 +188,10 @@ BigInt.prototype.sum = function (others: BigNumberish[]) { return sum(this as bigint, others); }; BigInt.prototype.format = function (decimals?: number, digits?: number) { - const formatted = formatUnits(this as bigint, decimals); - - let dotIndex = formatted.indexOf("."); - if (dotIndex < 0) dotIndex = formatted.length; - - decimals = formatted.length - 1 - dotIndex; - digits ??= decimals; - - return digits < decimals - ? formatted.slice(0, dotIndex + (digits > 0 ? digits + 1 : 0)) - : formatted + "0".repeat(digits - decimals); + return format(this as bigint, decimals, digits); }; BigInt.prototype.toFloat = function (decimals?: number) { - return parseFloat(this.format(decimals)); + return toFloat(this as bigint, decimals); }; BigInt.prototype.mulDiv = function (other: BigNumberish, scale: BigNumberish) { @@ -156,193 +205,175 @@ BigInt.prototype.mulDivDown = function (other: BigNumberish, scale: BigNumberish }; BigInt.prototype.compMul = function (other: BigNumberish) { - return ((this as bigint) * toBigInt(other)) / WAD; + return compMul(this as bigint, other); }; BigInt.prototype.compDiv = function (other: BigNumberish) { - return ((this as bigint) * WAD_SQUARED) / toBigInt(other) / WAD; + return compDiv(this as bigint, other); }; BigInt.prototype.percentAdd = function (pct: BigNumberish) { - return this.percentMul(PERCENT + toBigInt(pct)); + return percentAdd(this as bigint, pct); }; BigInt.prototype.percentSub = function (pct: BigNumberish) { - return this.percentMul(PERCENT - toBigInt(pct)); + return percentSub(this as bigint, pct); }; BigInt.prototype.percentMul = function (other: BigNumberish) { - return mulDivHalfUp(this as bigint, other, PERCENT); + return percentMul(this as bigint, other); }; BigInt.prototype.percentMulUp = function (other: BigNumberish) { - return mulDivUp(this as bigint, other, PERCENT); + return percentMulUp(this as bigint, other); }; BigInt.prototype.percentMulDown = function (other: BigNumberish) { - return mulDivDown(this as bigint, other, PERCENT); + return percentMulDown(this as bigint, other); }; BigInt.prototype.percentDiv = function (other: BigNumberish) { - return mulDivHalfUp(this as bigint, PERCENT, other); + return percentDiv(this as bigint, other); }; BigInt.prototype.percentDivUp = function (other: BigNumberish) { - return mulDivUp(this as bigint, PERCENT, other); + return percentDivUp(this as bigint, other); }; BigInt.prototype.percentDivDown = function (other: BigNumberish) { - return mulDivDown(this as bigint, PERCENT, other); + return percentDivDown(this as bigint, other); }; BigInt.prototype.percentAvg = function (other: BigNumberish, pct: BigNumberish) { - return avgHalfUp(this as bigint, other, pct, PERCENT); + return percentAvg(this as bigint, other, pct); }; BigInt.prototype.percentPow = function (exponent: BigNumberish) { - return pow(this as bigint, exponent, PERCENT, mulDivHalfUp); + return percentPow(this as bigint, exponent); }; BigInt.prototype.percentPowUp = function (exponent: BigNumberish) { - return pow(this as bigint, exponent, PERCENT, mulDivUp); + return percentPowUp(this as bigint, exponent); }; BigInt.prototype.percentPowDown = function (exponent: BigNumberish) { - return pow(this as bigint, exponent, PERCENT, mulDivDown); + return percentPowDown(this as bigint, exponent); }; BigInt.prototype.percentExpN = function (N: BigNumberish) { - return expN(this as bigint, N, PERCENT, mulDivDown); + return percentExpN(this as bigint, N); }; BigInt.prototype.percentToDecimals = function (decimals: number) { - if (decimals <= 4) { - const ratio = pow10(4 - decimals); - - return ((this as bigint) + ratio / 2n) / ratio; - } - - return (this as bigint) * pow10(decimals - 4); + return percentToDecimals(this as bigint, decimals); }; BigInt.prototype.percentToWad = function () { - return this.percentToDecimals(18); + return percentToWad(this as bigint); }; BigInt.prototype.percentToRay = function () { - return this.percentToDecimals(27); + return percentToRay(this as bigint); }; BigInt.prototype.formatPercent = function (digits?: number) { - return this.format(4, digits); + return formatPercent(this as bigint, digits); }; BigInt.prototype.toPercentFloat = function () { - return this.toFloat(4); + return toPercentFloat(this as bigint); }; BigInt.prototype.wadAdd = function (wad: BigNumberish) { - return this.wadMul(WAD + toBigInt(wad)); + return wadAdd(this as bigint, wad); }; BigInt.prototype.wadSub = function (wad: BigNumberish) { - return this.wadMul(WAD - toBigInt(wad)); + return wadSub(this as bigint, wad); }; BigInt.prototype.wadMul = function (other: BigNumberish) { - return mulDivHalfUp(this as bigint, other, WAD); + return wadMul(this as bigint, other); }; BigInt.prototype.wadMulUp = function (other: BigNumberish) { - return mulDivUp(this as bigint, other, WAD); + return wadMulUp(this as bigint, other); }; BigInt.prototype.wadMulDown = function (other: BigNumberish) { - return mulDivDown(this as bigint, other, WAD); + return wadMulDown(this as bigint, other); }; BigInt.prototype.wadDiv = function (other: BigNumberish) { - return mulDivHalfUp(this as bigint, WAD, other); + return wadDiv(this as bigint, other); }; BigInt.prototype.wadDivUp = function (other: BigNumberish) { - return mulDivUp(this as bigint, WAD, other); + return wadDivUp(this as bigint, other); }; BigInt.prototype.wadDivDown = function (other: BigNumberish) { - return mulDivDown(this as bigint, WAD, other); + return wadDivDown(this as bigint, other); }; BigInt.prototype.wadAvg = function (other: BigNumberish, wad: BigNumberish) { - return avgHalfUp(this as bigint, other, wad, WAD); + return wadAvg(this as bigint, other, wad); }; BigInt.prototype.wadPow = function (exponent: BigNumberish) { - return pow(this as bigint, exponent, WAD, mulDivHalfUp); + return wadPow(this as bigint, exponent); }; BigInt.prototype.wadPowUp = function (exponent: BigNumberish) { - return pow(this as bigint, exponent, WAD, mulDivUp); + return wadPowUp(this as bigint, exponent); }; BigInt.prototype.wadPowDown = function (exponent: BigNumberish) { - return pow(this as bigint, exponent, WAD, mulDivDown); + return wadPowDown(this as bigint, exponent); }; BigInt.prototype.wadExpN = function (N: BigNumberish) { - return expN(this as bigint, N, WAD, mulDivDown); + return wadExpN(this as bigint, N); }; BigInt.prototype.wadToDecimals = function (decimals: number) { - if (decimals <= 18) { - const ratio = pow10(18 - decimals); - - return ((this as bigint) + ratio / 2n) / ratio; - } - - return (this as bigint) * pow10(decimals - 18); + return wadToDecimals(this as bigint, decimals); }; BigInt.prototype.wadToPercent = function () { - return this.wadToDecimals(4); + return wadToPercent(this as bigint); }; BigInt.prototype.wadToRay = function () { - return this.wadToDecimals(27); + return wadToRay(this as bigint); }; BigInt.prototype.formatWad = function (digits?: number) { - return this.format(18, digits); + return formatWad(this as bigint, digits); }; BigInt.prototype.toWadFloat = function () { - return this.toFloat(18); + return toWadFloat(this as bigint); }; BigInt.prototype.rayAdd = function (ray: BigNumberish) { - return this.rayMul(RAY + toBigInt(ray)); + return rayAdd(this as bigint, ray); }; BigInt.prototype.raySub = function (ray: BigNumberish) { - return this.rayMul(RAY - toBigInt(ray)); + return raySub(this as bigint, ray); }; BigInt.prototype.rayMul = function (other: BigNumberish) { - return mulDivHalfUp(this as bigint, other, RAY); + return rayMul(this as bigint, other); }; BigInt.prototype.rayMulUp = function (other: BigNumberish) { - return mulDivUp(this as bigint, other, RAY); + return rayMulUp(this as bigint, other); }; BigInt.prototype.rayMulDown = function (other: BigNumberish) { - return mulDivDown(this as bigint, other, RAY); + return rayMulDown(this as bigint, other); }; BigInt.prototype.rayDiv = function (other: BigNumberish) { - return mulDivHalfUp(this as bigint, RAY, other); + return rayDiv(this as bigint, other); }; BigInt.prototype.rayDivUp = function (other: BigNumberish) { - return mulDivUp(this as bigint, RAY, other); + return rayDivUp(this as bigint, other); }; BigInt.prototype.rayDivDown = function (other: BigNumberish) { - return mulDivDown(this as bigint, RAY, other); + return rayDivDown(this as bigint, other); }; BigInt.prototype.rayAvg = function (other: BigNumberish, ray: BigNumberish) { - return avgHalfUp(this as bigint, other, ray, RAY); + return rayAvg(this as bigint, other, ray); }; BigInt.prototype.rayPow = function (exponent: BigNumberish) { - return pow(this as bigint, exponent, RAY, mulDivHalfUp); + return rayPow(this as bigint, exponent); }; BigInt.prototype.rayPowUp = function (exponent: BigNumberish) { - return pow(this as bigint, exponent, RAY, mulDivUp); + return rayPowUp(this as bigint, exponent); }; BigInt.prototype.rayPowDown = function (exponent: BigNumberish) { - return pow(this as bigint, exponent, RAY, mulDivDown); + return rayPowDown(this as bigint, exponent); }; BigInt.prototype.rayExpN = function (N: BigNumberish) { - return expN(this as bigint, N, RAY, mulDivDown); + return rayExpN(this as bigint, N); }; BigInt.prototype.rayToDecimals = function (decimals: number) { - if (decimals <= 27) { - const ratio = pow10(27 - decimals); - - return ((this as bigint) + ratio / 2n) / ratio; - } - - return (this as bigint) * pow10(decimals - 27); + return rayToDecimals(this as bigint, decimals); }; BigInt.prototype.rayToPercent = function () { - return this.rayToDecimals(4); + return rayToPercent(this as bigint); }; BigInt.prototype.rayToWad = function () { - return this.rayToDecimals(18); + return rayToWad(this as bigint); }; BigInt.prototype.formatRay = function (digits?: number) { - return this.format(27, digits); + return formatRay(this as bigint, digits); }; BigInt.prototype.toRayFloat = function () { - return this.toFloat(27); + return toRayFloat(this as bigint); }; BigInt.PERCENT = PERCENT; diff --git a/src/percent.ts b/src/percent.ts new file mode 100644 index 0000000..c6d7c70 --- /dev/null +++ b/src/percent.ts @@ -0,0 +1,78 @@ +import { BigNumberish, parseUnits, toBigInt } from "ethers"; +import { PERCENT } from "./constants"; +import { avgHalfUp, expN, mulDivDown, mulDivHalfUp, mulDivUp, pow } from "./utils"; +import { format, toDecimals, toFloat } from "./format"; + +export const parsePercent = (value: string) => parseUnits(value, 2); + +export const percentAdd = (x: BigNumberish, percent: BigNumberish) => { + return percentMul(x, PERCENT + toBigInt(percent)); +}; + +export const percentSub = (x: BigNumberish, percent: BigNumberish) => { + return percentMul(x, PERCENT - toBigInt(percent)); +}; + +export const percentMul = (x: BigNumberish, other: BigNumberish) => { + return mulDivHalfUp(x, other, PERCENT); +}; + +export const percentMulUp = (x: BigNumberish, other: BigNumberish) => { + return mulDivUp(x, other, PERCENT); +}; + +export const percentMulDown = (x: BigNumberish, other: BigNumberish) => { + return mulDivDown(x, other, PERCENT); +}; + +export const percentDiv = (x: BigNumberish, other: BigNumberish) => { + return mulDivHalfUp(x, PERCENT, other); +}; + +export const percentDivUp = (x: BigNumberish, other: BigNumberish) => { + return mulDivUp(x, PERCENT, other); +}; + +export const percentDivDown = (x: BigNumberish, other: BigNumberish) => { + return mulDivDown(x, PERCENT, other); +}; + +export const percentAvg = (x: BigNumberish, other: BigNumberish, percent: BigNumberish) => { + return avgHalfUp(x, other, percent, PERCENT); +}; + +export const percentPow = (x: BigNumberish, exponent: BigNumberish) => { + return pow(x, exponent, PERCENT, mulDivHalfUp); +}; + +export const percentPowUp = (x: BigNumberish, exponent: BigNumberish) => { + return pow(x, exponent, PERCENT, mulDivUp); +}; + +export const percentPowDown = (x: BigNumberish, exponent: BigNumberish) => { + return pow(x, exponent, PERCENT, mulDivDown); +}; + +export const percentExpN = (x: BigNumberish, N: BigNumberish) => { + return expN(x, N, PERCENT, mulDivDown); +}; + +export const percentToDecimals = (x: BigNumberish, decimals: number) => { + return toDecimals(x, decimals, 4); +}; + +export const percentToRay = (x: BigNumberish) => { + return percentToDecimals(x, 27); +}; + +export const percentToWad = (x: BigNumberish) => { + return percentToDecimals(x, 18); +}; + +export const formatPercent = (x: BigNumberish, digits?: number) => { + return format(x, 4, digits); +}; + +export const toPercentFloat = (x: BigNumberish) => { + return toFloat(x, 4); +}; diff --git a/src/ray.ts b/src/ray.ts new file mode 100644 index 0000000..166998c --- /dev/null +++ b/src/ray.ts @@ -0,0 +1,78 @@ +import { BigNumberish, parseUnits, toBigInt } from "ethers"; +import { RAY } from "./constants"; +import { avgHalfUp, expN, mulDivDown, mulDivHalfUp, mulDivUp, pow } from "./utils"; +import { format, toDecimals, toFloat } from "./format"; + +export const parseRay = (value: string) => parseUnits(value, 27); + +export const rayAdd = (x: BigNumberish, ray: BigNumberish) => { + return rayMul(x, RAY + toBigInt(ray)); +}; + +export const raySub = (x: BigNumberish, ray: BigNumberish) => { + return rayMul(x, RAY - toBigInt(ray)); +}; + +export const rayMul = (x: BigNumberish, other: BigNumberish) => { + return mulDivHalfUp(x, other, RAY); +}; + +export const rayMulUp = (x: BigNumberish, other: BigNumberish) => { + return mulDivUp(x, other, RAY); +}; + +export const rayMulDown = (x: BigNumberish, other: BigNumberish) => { + return mulDivDown(x, other, RAY); +}; + +export const rayDiv = (x: BigNumberish, other: BigNumberish) => { + return mulDivHalfUp(x, RAY, other); +}; + +export const rayDivUp = (x: BigNumberish, other: BigNumberish) => { + return mulDivUp(x, RAY, other); +}; + +export const rayDivDown = (x: BigNumberish, other: BigNumberish) => { + return mulDivDown(x, RAY, other); +}; + +export const rayAvg = (x: BigNumberish, other: BigNumberish, ray: BigNumberish) => { + return avgHalfUp(x, other, ray, RAY); +}; + +export const rayPow = (x: BigNumberish, exponent: BigNumberish) => { + return pow(x, exponent, RAY, mulDivHalfUp); +}; + +export const rayPowUp = (x: BigNumberish, exponent: BigNumberish) => { + return pow(x, exponent, RAY, mulDivUp); +}; + +export const rayPowDown = (x: BigNumberish, exponent: BigNumberish) => { + return pow(x, exponent, RAY, mulDivDown); +}; + +export const rayExpN = (x: BigNumberish, N: BigNumberish) => { + return expN(x, N, RAY, mulDivDown); +}; + +export const rayToDecimals = (x: BigNumberish, decimals: number) => { + return toDecimals(x, decimals, 27); +}; + +export const rayToPercent = (x: BigNumberish) => { + return rayToDecimals(x, 4); +}; + +export const rayToWad = (x: BigNumberish) => { + return rayToDecimals(x, 18); +}; + +export const formatRay = (x: BigNumberish, digits?: number) => { + return format(x, 27, digits); +}; + +export const toRayFloat = (x: BigNumberish) => { + return toFloat(x, 27); +}; diff --git a/src/utils.ts b/src/utils.ts index 857d26e..de4e0a9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,4 @@ -import { BigNumberish, parseUnits, toBigInt } from "ethers"; +import { BigNumberish, toBigInt } from "ethers"; export type MulDiv = (x: BigNumberish, y: BigNumberish, scale: BigNumberish) => bigint; @@ -83,10 +83,6 @@ export const avgHalfUp = ( return (max(0, scale - pct) * x + min(scale, pct) * y + scale / 2n) / scale; }; -export const parsePercent = (value: string) => parseUnits(value, 2); -export const parseWad = (value: string) => parseUnits(value, 18); -export const parseRay = (value: string) => parseUnits(value, 27); - export const pow = ( x: BigNumberish, exponent: BigNumberish, diff --git a/src/wad.ts b/src/wad.ts new file mode 100644 index 0000000..8d9a7da --- /dev/null +++ b/src/wad.ts @@ -0,0 +1,78 @@ +import { BigNumberish, parseUnits, toBigInt } from "ethers"; +import { WAD } from "./constants"; +import { avgHalfUp, expN, mulDivDown, mulDivHalfUp, mulDivUp, pow } from "./utils"; +import { format, toDecimals, toFloat } from "./format"; + +export const parseWad = (value: string) => parseUnits(value, 18); + +export const wadAdd = (x: BigNumberish, wad: BigNumberish) => { + return wadMul(x, WAD + toBigInt(wad)); +}; + +export const wadSub = (x: BigNumberish, wad: BigNumberish) => { + return wadMul(x, WAD - toBigInt(wad)); +}; + +export const wadMul = (x: BigNumberish, other: BigNumberish) => { + return mulDivHalfUp(x, other, WAD); +}; + +export const wadMulUp = (x: BigNumberish, other: BigNumberish) => { + return mulDivUp(x, other, WAD); +}; + +export const wadMulDown = (x: BigNumberish, other: BigNumberish) => { + return mulDivDown(x, other, WAD); +}; + +export const wadDiv = (x: BigNumberish, other: BigNumberish) => { + return mulDivHalfUp(x, WAD, other); +}; + +export const wadDivUp = (x: BigNumberish, other: BigNumberish) => { + return mulDivUp(x, WAD, other); +}; + +export const wadDivDown = (x: BigNumberish, other: BigNumberish) => { + return mulDivDown(x, WAD, other); +}; + +export const wadAvg = (x: BigNumberish, other: BigNumberish, wad: BigNumberish) => { + return avgHalfUp(x, other, wad, WAD); +}; + +export const wadPow = (x: BigNumberish, exponent: BigNumberish) => { + return pow(x, exponent, WAD, mulDivHalfUp); +}; + +export const wadPowUp = (x: BigNumberish, exponent: BigNumberish) => { + return pow(x, exponent, WAD, mulDivUp); +}; + +export const wadPowDown = (x: BigNumberish, exponent: BigNumberish) => { + return pow(x, exponent, WAD, mulDivDown); +}; + +export const wadExpN = (x: BigNumberish, N: BigNumberish) => { + return expN(x, N, WAD, mulDivDown); +}; + +export const wadToDecimals = (x: BigNumberish, decimals: number) => { + return toDecimals(x, decimals, 18); +}; + +export const wadToPercent = (x: BigNumberish) => { + return wadToDecimals(x, 4); +}; + +export const wadToRay = (x: BigNumberish) => { + return wadToDecimals(x, 27); +}; + +export const formatWad = (x: BigNumberish, digits?: number) => { + return format(x, 18, digits); +}; + +export const toWadFloat = (x: BigNumberish) => { + return toFloat(x, 18); +};