diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000..de8f622 --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,15 @@ +import { pow10 } from "./utils"; + +export const PERCENT = pow10(4); +export const WAD = pow10(18); +export const RAY = pow10(27); +export const WAD_SQUARED = WAD.pow(2); + +export const RAY_WAD_RATIO = RAY.div(WAD); +export const HALF_RAY_WAD_RATIO = RAY_WAD_RATIO.div(2); + +export const WAD_PERCENT_RATIO = WAD.div(PERCENT); +export const HALF_WAD_PERCENT_RATIO = WAD_PERCENT_RATIO.div(2); + +export const RAY_PERCENT_RATIO = RAY.div(PERCENT); +export const HALF_RAY_PERCENT_RATIO = RAY_PERCENT_RATIO.div(2); diff --git a/src/index.ts b/src/index.ts index d1fe836..7296aba 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,20 +1,19 @@ import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; -import { formatUnits, parseUnits } from "@ethersproject/units"; - -import { avgUp, max, min, mulDivUp, pow10 } from "./utils"; - -export const PERCENT = pow10(4); -export const WAD = pow10(18); -export const RAY = pow10(27); - -const RAY_WAD_RATIO = RAY.div(WAD); -const HALF_RAY_WAD_RATIO = RAY_WAD_RATIO.div(2); - -const WAD_PERCENT_RATIO = WAD.div(PERCENT); -const HALF_WAD_PERCENT_RATIO = WAD_PERCENT_RATIO.div(2); - -const RAY_PERCENT_RATIO = RAY.div(PERCENT); -const HALF_RAY_PERCENT_RATIO = RAY_PERCENT_RATIO.div(2); +import { formatUnits } from "@ethersproject/units"; + +import { + HALF_RAY_PERCENT_RATIO, + HALF_RAY_WAD_RATIO, + HALF_WAD_PERCENT_RATIO, + PERCENT, + RAY, + RAY_PERCENT_RATIO, + RAY_WAD_RATIO, + WAD, + WAD_PERCENT_RATIO, + WAD_SQUARED, +} from "./constants"; +import { avgUp, max, min, pow10, mulDivUp, parsePercent, parseRay, parseWad } from "./utils"; declare module "@ethersproject/bignumber/lib/bignumber" { interface BigNumber { @@ -76,10 +75,10 @@ BigNumber.prototype.sum = function (others: BigNumberish[]) { }; BigNumber.prototype.compMul = function (other: BigNumberish) { - return BigNumber.from(this).mul(other).div(WAD); + return this.mul(other).div(WAD); }; BigNumber.prototype.compDiv = function (other: BigNumberish) { - return WAD.mul(this).mul(WAD).div(other).div(WAD); + return this.mul(WAD_SQUARED).div(other).div(WAD); }; BigNumber.prototype.percentAdd = function (pct: BigNumberish) { @@ -108,10 +107,10 @@ BigNumber.prototype.formatPercent = function () { }; BigNumber.prototype.wadAdd = function (wad: BigNumberish) { - return this.wadMul(PERCENT.add(wad)); + return this.wadMul(WAD.add(wad)); }; BigNumber.prototype.wadSub = function (wad: BigNumberish) { - return this.wadMul(PERCENT.sub(wad)); + return this.wadMul(WAD.sub(wad)); }; BigNumber.prototype.wadMul = function (other: BigNumberish) { return mulDivUp(this, other, WAD); @@ -133,10 +132,10 @@ BigNumber.prototype.formatWad = function () { }; BigNumber.prototype.rayAdd = function (ray: BigNumberish) { - return this.rayMul(PERCENT.add(ray)); + return this.rayMul(RAY.add(ray)); }; BigNumber.prototype.raySub = function (ray: BigNumberish) { - return this.rayMul(PERCENT.sub(ray)); + return this.rayMul(RAY.sub(ray)); }; BigNumber.prototype.rayMul = function (other: BigNumberish) { return mulDivUp(this, other, RAY); @@ -162,12 +161,6 @@ BigNumber.WAD = WAD; BigNumber.RAY = RAY; BigNumber.pow10 = pow10; -BigNumber.parsePercent = function (value: string) { - return parseUnits(value, 2); -}; -BigNumber.parseWad = function (value: string) { - return parseUnits(value, 18); -}; -BigNumber.parseRay = function (value: string) { - return parseUnits(value, 27); -}; +BigNumber.parsePercent = parsePercent; +BigNumber.parseWad = parseWad; +BigNumber.parseRay = parseRay; diff --git a/src/utils.ts b/src/utils.ts index 3846649..c3d18d1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,5 @@ import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; +import { parseUnits } from "@ethersproject/units"; export const pow10 = (power: BigNumberish) => BigNumber.from(10).pow(power); @@ -30,3 +31,7 @@ export const avgUp = (x: BigNumberish, y: BigNumberish, pct: BigNumberish, scale return max(0, scale.sub(pct)).mul(x).add(min(scale, pct).mul(y)).add(scale.div(2)).div(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); diff --git a/test/index.spec.ts b/test/index.spec.ts index e8101aa..de8c062 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -2,8 +2,58 @@ import { BigNumber } from "@ethersproject/bignumber"; import "../src"; +const ZERO = "0"; +const WAD = BigNumber.WAD.toString(); +const RAY = BigNumber.RAY.toString(); + +const TWO_WAD = BigNumber.WAD.mul(2).toString(); + describe("ethers-maths", () => { - it("should overload", async () => { - BigNumber.from(0).wadMul(1); + it("should return minimum", async () => { + expect(BigNumber.WAD.min(0).toString()).toEqual(ZERO); + expect(BigNumber.WAD.min(BigNumber.RAY).toString()).toEqual(WAD); + }); + + it("should return maximum", async () => { + expect(BigNumber.WAD.max(0).toString()).toEqual(WAD); + expect(BigNumber.WAD.max(BigNumber.RAY).toString()).toEqual(RAY); + }); + + it("should average", async () => { + expect( + BigNumber.WAD.percentAvg(BigNumber.WAD.mul(3), BigNumber.PERCENT.div(2)).toString() + ).toEqual(TWO_WAD); + expect(BigNumber.WAD.wadAvg(BigNumber.WAD.mul(3), BigNumber.WAD.div(2)).toString()).toEqual( + TWO_WAD + ); + expect(BigNumber.WAD.rayAvg(BigNumber.WAD.mul(3), BigNumber.RAY.div(2)).toString()).toEqual( + TWO_WAD + ); + }); + + it("should double on addition", async () => { + expect(BigNumber.WAD.percentAdd(BigNumber.PERCENT).toString()).toEqual(TWO_WAD); + expect(BigNumber.WAD.wadAdd(BigNumber.WAD).toString()).toEqual(TWO_WAD); + expect(BigNumber.WAD.rayAdd(BigNumber.RAY).toString()).toEqual(TWO_WAD); + }); + + it("should zero on subtraction", async () => { + expect(BigNumber.WAD.percentSub(BigNumber.PERCENT).toString()).toEqual(ZERO); + expect(BigNumber.WAD.wadSub(BigNumber.WAD).toString()).toEqual(ZERO); + expect(BigNumber.WAD.raySub(BigNumber.RAY).toString()).toEqual(ZERO); + }); + + it("should preserve units on multiplication", async () => { + expect(BigNumber.WAD.percentMul(BigNumber.PERCENT).toString()).toEqual(WAD); + expect(BigNumber.WAD.compMul(BigNumber.WAD).toString()).toEqual(WAD); + expect(BigNumber.WAD.wadMul(BigNumber.WAD).toString()).toEqual(WAD); + expect(BigNumber.WAD.rayMul(BigNumber.RAY).toString()).toEqual(WAD); + }); + + it("should preserve units on division", async () => { + expect(BigNumber.WAD.percentDiv(BigNumber.PERCENT).toString()).toEqual(WAD); + expect(BigNumber.WAD.compDiv(BigNumber.WAD).toString()).toEqual(WAD); + expect(BigNumber.WAD.wadDiv(BigNumber.WAD).toString()).toEqual(WAD); + expect(BigNumber.WAD.rayDiv(BigNumber.RAY).toString()).toEqual(WAD); }); });