UNPKG

@ckb-lumos/bi

Version:
264 lines (259 loc) 7.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ckbDecimals = exports.BI = void 0; exports.formatUnit = formatUnit; exports.isBIish = isBIish; exports.parseUnit = parseUnit; exports.toJSBI = toJSBI; var _jsbi = _interopRequireDefault(require("jsbi")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function isBIish(value) { return value !== null && (typeof value === "number" && value % 1 === 0 || typeof value === "string" && (!!value.match(/^0x(0|[0-9a-fA-F]+)$/) || !!value.match(/^-?[0-9]+$/)) || typeof value === "bigint" || BI.isBI(value)); } class BI { constructor(value) { this.jsbi = value; this._isBI = true; } add(other) { return toBI(_jsbi.default.add(this.jsbi, toJSBI(other))); } sub(other) { return toBI(_jsbi.default.subtract(this.jsbi, toJSBI(other))); } div(other) { return toBI(_jsbi.default.divide(this.jsbi, toJSBI(other))); } mul(other) { return toBI(_jsbi.default.multiply(this.jsbi, toJSBI(other))); } mod(other) { return toBI(_jsbi.default.remainder(this.jsbi, toJSBI(other))); } abs() { if (_jsbi.default.greaterThanOrEqual(this.jsbi, toJSBI(0))) { return toBI(this.jsbi); } else { return toBI(_jsbi.default.unaryMinus(this.jsbi)); } } pow(other) { return toBI(_jsbi.default.exponentiate(this.jsbi, toJSBI(other))); } and(other) { return toBI(_jsbi.default.bitwiseAnd(this.jsbi, toJSBI(other))); } or(other) { return toBI(_jsbi.default.bitwiseOr(this.jsbi, toJSBI(other))); } xor(other) { return toBI(_jsbi.default.bitwiseXor(this.jsbi, toJSBI(other))); } not() { return toBI(_jsbi.default.bitwiseNot(this.jsbi)); } mask(other) { const jsbiOther = toJSBI(other); if (_jsbi.default.lessThan(jsbiOther, toJSBI(0)) || _jsbi.default.lessThan(this.jsbi, toJSBI(0))) { throw new Error("mask works only with positive numbers"); } const length = toJSBI(this.jsbi.toString(2).length); if (_jsbi.default.lessThanOrEqual(length, jsbiOther)) { return toBI(this.jsbi); } else { const maskNum = _jsbi.default.leftShift(_jsbi.default.signedRightShift(this.jsbi, jsbiOther), jsbiOther); return toBI(_jsbi.default.bitwiseXor(this.jsbi, maskNum)); } } shl(other) { return toBI(_jsbi.default.leftShift(this.jsbi, toJSBI(other))); } shr(other) { return toBI(_jsbi.default.signedRightShift(this.jsbi, toJSBI(other))); } eq(other) { return _jsbi.default.equal(this.jsbi, toJSBI(other)); } lt(other) { return _jsbi.default.lessThan(this.jsbi, toJSBI(other)); } lte(other) { return _jsbi.default.lessThanOrEqual(this.jsbi, toJSBI(other)); } gt(other) { return _jsbi.default.greaterThan(this.jsbi, toJSBI(other)); } gte(other) { return _jsbi.default.greaterThanOrEqual(this.jsbi, toJSBI(other)); } isNegative() { return _jsbi.default.lessThan(this.jsbi, toJSBI(0)); } isZero() { return _jsbi.default.equal(this.jsbi, toJSBI(0)); } toNumber() { return _jsbi.default.toNumber(this.jsbi); } toBigInt() { try { return BigInt(this.jsbi.toString(10)); } catch (e) { throw new Error("this platform does not support BigInt"); } } toString(radix) { radix = radix || 10; return this.jsbi.toString(radix); } toHexString() { if (_jsbi.default.lessThan(this.jsbi, toJSBI(0))) { return "-0x" + _jsbi.default.unaryMinus(this.jsbi).toString(16); } else { return "0x" + this.jsbi.toString(16); } } static from(value) { if (value instanceof BI) { return value; } else if (isBIish(value)) { return toBI(toJSBI(value)); } else if (value instanceof _jsbi.default) { return toBI(toJSBI(value.toString())); } else { throw new Error(`invalid type: ${value} can't be converted into BI`); } } static isBI(value) { return isBILike(value) && !!value._isBI; } } exports.BI = BI; function isBILike(value) { if (value == null) return false; return typeof value === "object"; } function toBI(value) { return new BI(value); } function toJSBI(value) { if (typeof value === "number" || typeof value === "string") { return _jsbi.default.BigInt(value); } else { return _jsbi.default.BigInt(value.toString()); } } const validUnitNames = ["shannon", "ckb"]; const ckbDecimals = exports.ckbDecimals = 8; const negativeOne = BI.from(-1); function formatUnit(value, unit) { const decimals = parseDecimals(unit); return formatFixed(value, decimals); } function parseUnit(value, unit) { const decimals = parseDecimals(unit); return parseFixed(value, decimals); } function formatFixed(value, decimals) { if (!isValidDecimalSize(decimals)) { throw new Error(`decimal size must be a non-negative integer`); } const multiplier = "1" + Array(decimals).fill("0").join(""); value = BI.from(value); const isNegative = value.isNegative(); if (isNegative) { value = value.mul(negativeOne); } const wholePart = value.div(multiplier).toString(); let result = wholePart; if (multiplier.length > 1) { let decimalPart = value.mod(multiplier).toString(); while (decimalPart.length < multiplier.length - 1) { decimalPart = "0" + decimalPart; } // remove trailing zeros decimalPart = decimalPart.match(/^([0-9]*[1-9]|0)(0*)/)[1]; result += "." + decimalPart; } if (isNegative) { result = "-" + result; } return result; } function parseFixed(value, decimals) { if (!isValidDecimalSize(decimals)) { throw new Error(`decimal size must be a non-negative integer`); } // check if value represents a valid decimal number if (!value.match(/^-?\d+(\.\d{1,})?$/)) { throw new Error("invalid decimal string"); } const multiplier = "1" + Array(decimals).fill("0").join(""); const isNegative = value.substring(0, 1) === "-"; if (isNegative) { value = value.substring(1); } let wholePart, decimalPart; const valueParts = value.split("."); if (valueParts.length === 1) { wholePart = valueParts[0]; decimalPart = "0"; } else if (valueParts.length === 2) { wholePart = valueParts[0]; decimalPart = valueParts[1]; } else { throw new Error("too many decimal points (should not happen)"); } // remove leading zeros of whole part while (wholePart.length > 0 && wholePart[0] === "0") { wholePart = wholePart.substring(1); } if (wholePart === "") { wholePart = "0"; } // remove trailing zeros of decimal part while (decimalPart.length > 0 && decimalPart[decimalPart.length - 1] === "0") { decimalPart = decimalPart.substring(0, decimalPart.length - 1); } if (decimalPart.length > multiplier.length - 1) { throw new Error("decimal part exceeds max decimals"); } if (decimalPart === "") { decimalPart = "0"; } // pad decimal part with zeros to get to shannon while (decimalPart.length < multiplier.length - 1) { decimalPart += "0"; } const wholeValue = BI.from(wholePart); const decimalValue = BI.from(decimalPart); let shannons = wholeValue.mul(multiplier).add(decimalValue); if (isNegative) { shannons = shannons.mul(negativeOne); } return shannons; } function parseDecimals(unit) { let decimals = 0; if (typeof unit === "string") { if (validUnitNames.indexOf(unit) === -1) { throw new Error(`invalid unit name, supported names are ${validUnitNames.join(", ")}`); } if (unit === "ckb") { decimals = ckbDecimals; } } else { if (isValidDecimalSize(unit)) { decimals = unit; } else { throw new Error(`unit of integer must be a non-negative integer`); } } return decimals; } function isValidDecimalSize(decimals) { return Number.isInteger(decimals) && decimals >= 0; } //# sourceMappingURL=index.js.map