Skip to content

Instantly share code, notes, and snippets.

@petejkim
Created September 23, 2021 21:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petejkim/7c43d543916b9bd3cc864b852b01584e to your computer and use it in GitHub Desktop.
Save petejkim/7c43d543916b9bd3cc864b852b01584e to your computer and use it in GitHub Desktop.
decimal string <> BN
import BN from "bn.js";
import * as types from "./types";
test("decimalStringFromBN", () => {
expect(types.decimalStringFromBN(new BN(0))).toEqual("0");
expect(types.decimalStringFromBN(new BN(0), 1)).toEqual("0");
expect(types.decimalStringFromBN(new BN(1000000))).toEqual("1000000");
expect(types.decimalStringFromBN(new BN(1000000), 1)).toEqual("100000");
expect(types.decimalStringFromBN(new BN(1000001), 1)).toEqual("100000.1");
expect(types.decimalStringFromBN(new BN(1000100), 1)).toEqual("100010");
expect(types.decimalStringFromBN(new BN(1000000), 2)).toEqual("10000");
expect(types.decimalStringFromBN(new BN(1000001), 2)).toEqual("10000.01");
expect(types.decimalStringFromBN(new BN(1000100), 2)).toEqual("10001");
expect(types.decimalStringFromBN(new BN(1000000), 5)).toEqual("10");
expect(types.decimalStringFromBN(new BN(1000001), 5)).toEqual("10.00001");
expect(types.decimalStringFromBN(new BN(1000100), 5)).toEqual("10.001");
expect(types.decimalStringFromBN(new BN(1000000), 6)).toEqual("1");
expect(types.decimalStringFromBN(new BN(1000001), 6)).toEqual("1.000001");
expect(types.decimalStringFromBN(new BN(1000100), 6)).toEqual("1.0001");
expect(types.decimalStringFromBN(new BN(1000000), 7)).toEqual("0.1");
expect(types.decimalStringFromBN(new BN(1000001), 7)).toEqual("0.1000001");
expect(types.decimalStringFromBN(new BN(1000100), 7)).toEqual("0.10001");
expect(types.decimalStringFromBN(new BN(1000000), 8)).toEqual("0.01");
expect(types.decimalStringFromBN(new BN(1000001), 8)).toEqual("0.01000001");
expect(types.decimalStringFromBN(new BN(1000100), 8)).toEqual("0.010001");
expect(types.decimalStringFromBN(new BN(1000000), 10)).toEqual("0.0001");
expect(types.decimalStringFromBN(new BN(1000001), 10)).toEqual(
"0.0001000001"
);
expect(types.decimalStringFromBN(new BN(1000100), 10)).toEqual("0.00010001");
expect(types.decimalStringFromBN(new BN("3141592653589793238"), 18)).toEqual(
"3.141592653589793238"
);
expect(() => types.decimalStringFromBN(new BN(-1))).toThrow();
});
test("bnFromDecimalString", () => {
expect(types.bnFromDecimalString("0")).toEqual(new BN(0));
expect(types.bnFromDecimalString("0", 1)).toEqual(new BN(0));
expect(types.bnFromDecimalString("1000000")).toEqual(new BN(1000000));
expect(types.bnFromDecimalString("100000", 1)).toEqual(new BN(1000000));
expect(types.bnFromDecimalString("100000.1", 1)).toEqual(new BN(1000001));
expect(types.bnFromDecimalString("100010", 1)).toEqual(new BN(1000100));
expect(types.bnFromDecimalString("10000", 2)).toEqual(new BN(1000000));
expect(types.bnFromDecimalString("10000.01", 2)).toEqual(new BN(1000001));
expect(types.bnFromDecimalString("10001", 2)).toEqual(new BN(1000100));
expect(types.bnFromDecimalString("10", 5)).toEqual(new BN(1000000));
expect(types.bnFromDecimalString("10.00001", 5)).toEqual(new BN(1000001));
expect(types.bnFromDecimalString("10.001", 5)).toEqual(new BN(1000100));
expect(types.bnFromDecimalString("1", 6)).toEqual(new BN(1000000));
expect(types.bnFromDecimalString("1.000001", 6)).toEqual(new BN(1000001));
expect(types.bnFromDecimalString("1.0001", 6)).toEqual(new BN(1000100));
expect(types.bnFromDecimalString("0.1", 7)).toEqual(new BN(1000000));
expect(types.bnFromDecimalString("0.1000001", 7)).toEqual(new BN(1000001));
expect(types.bnFromDecimalString("0.10001", 7)).toEqual(new BN(1000100));
expect(types.bnFromDecimalString("0.01", 8)).toEqual(new BN(1000000));
expect(types.bnFromDecimalString("0.01000001", 8)).toEqual(new BN(1000001));
expect(types.bnFromDecimalString("0.010001", 8)).toEqual(new BN(1000100));
expect(types.bnFromDecimalString("0.0001", 10)).toEqual(new BN(1000000));
expect(types.bnFromDecimalString("0.0001000001", 10)).toEqual(
new BN(1000001)
);
expect(types.bnFromDecimalString("0.00010001", 10)).toEqual(new BN(1000100));
expect(types.bnFromDecimalString("3.141592653589793238", 18)).toEqual(
new BN("3141592653589793238")
);
expect(types.bnFromDecimalString(".", 1)).toEqual(new BN(0));
expect(types.bnFromDecimalString("1.", 0)).toEqual(new BN(1));
expect(types.bnFromDecimalString("1.", 1)).toEqual(new BN(10));
expect(types.bnFromDecimalString("1.", 2)).toEqual(new BN(100));
expect(types.bnFromDecimalString(".1", 0)).toEqual(new BN(0));
expect(types.bnFromDecimalString(".1", 1)).toEqual(new BN(1));
expect(types.bnFromDecimalString(".1", 2)).toEqual(new BN(10));
expect(types.bnFromDecimalString(".10", 0)).toEqual(new BN(0));
expect(types.bnFromDecimalString(".10", 1)).toEqual(new BN(1));
expect(types.bnFromDecimalString(".10", 2)).toEqual(new BN(10));
expect(types.bnFromDecimalString("3.14159265", 2)).toEqual(new BN(314));
expect(() => types.bnFromDecimalString("-1")).toThrow();
});
import BN from "bn.js";
/**
* Convert a BN object to a hexadecimal string
* @param bn BN object
* @param addPrefix (Default: true) If true, prepends the string with "0x"
* @returns Hexadecimal string
*/
export function hexStringFromBN(bn: BN, addPrefix = true): string {
if (!BN.isBN(bn)) {
throw new TypeError("Given value is not a BN object");
}
const hex = bn.toString(16);
return addPrefix ? "0x" + hex : hex;
}
/**
* Convert a BN object to a string representation of a positive decimal number
* @param bn BN object
* @param decimalPlaces Number of decimal places
* @returns String representation of a positive decimal number
*/
export function decimalStringFromBN(bn: BN, decimalPlaces = 0): string {
if (bn.isNeg()) {
throw new Error("Number must be positive");
}
if (bn.isZero()) {
return "0";
}
let str = bn.toString(10).padStart(decimalPlaces + 1, "0");
if (decimalPlaces === 0) {
return str;
}
str = str.slice(0, -decimalPlaces) + "." + str.slice(-decimalPlaces);
str = str.replace(/\.0+$/, "");
if (str.includes(".")) {
str = str.replace(/0+$/, "");
}
return str;
}
/**
* Convert a string representation of a positive decimal number to BN object
* @param decimalNumber String representation of a positive decimal number
* @param decimalPlaces Number of decimal places
* @param varName Variable name to include in the error message
* @returns BN object
* @throws Error
*/
export function bnFromDecimalString(
decimalNumber: string,
decimalPlaces = 0,
varName?: string
): BN {
ensurePositiveDecimalString(decimalNumber, varName);
let [whole, fractional] = decimalNumber.split(".");
whole = whole || "0";
fractional = (fractional || "0")
.slice(0, decimalPlaces)
.padEnd(decimalPlaces, "0");
return new BN(whole + fractional, 10);
}
/**
* Return a given string if it contains a valid positive decimal number,
* otherwise throw a TypeError
* @param decimalNumber String representation of a positive decimal number
* @param varName Variable name to include in the error message
* @throws TypeError
* @returns Given string
*/
export function ensurePositiveDecimalString(
decimalNumber: string,
varName = "Given value"
): string {
if (decimalNumber.startsWith("-")) {
throw new TypeError(`${varName} must be positive`);
}
if (!decimalNumber || !/^\d*(\.\d*)?$/.test(decimalNumber)) {
throw new TypeError(`${varName} does not contain a valid decimal number`);
}
return decimalNumber;
}
/**
* Return a given number if it is a positive integer, otherwise throw a
* TypeError
* @param num Number
* @param varName Variable name to include in the error message
* @throws TypeError
* @returns Given number
*/
export function ensurePositiveInteger(
num: number,
varName = "Given value"
): number {
if (!Number.isInteger(num)) {
throw new TypeError(`${varName} is not an integer`);
}
if (num < 0) {
throw new TypeError(`${varName} must be positive`);
}
return num;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment