UNPKG

@stabilis/c9-shape-liquidity-getter

Version:

A library for calculating redemption values of concentrated liquidity positions for C9 shape liquidity.

239 lines (238 loc) 9.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.I192 = void 0; const decimal_js_1 = require("decimal.js"); // Configure Decimal.js to handle higher precision // We need at least 40 digits of precision to safely handle 18 decimal places during calculations decimal_js_1.Decimal.set({ precision: 40, rounding: decimal_js_1.Decimal.ROUND_DOWN }); /** * I192 class to mimic Scrypto Decimal's I192 behavior * * This class handles 192-bit representation of fixed-scale decimal numbers with 18 decimal places, * matching Scrypto's Decimal type as closely as possible. * * Key features: * 1. Represents numbers with exactly 18 decimal places of precision * 2. Performs truncation (toward zero) after each operation to match Scrypto's behavior * 3. Enforces the same value range as Scrypto's Decimal type * 4. Always outputs values with exactly 18 decimal places * * Truncation vs. Rounding: * - Scrypto's Decimal type truncates values toward zero after each operation * - For positive numbers, this means flooring the value (removing all digits beyond 18 decimals) * - For negative numbers, this means ceiling the value (removing all digits beyond 18 decimals) * - This is different from banker's rounding (which rounds to nearest, with ties to even) * - Truncation creates consistent, predictable behavior for financial calculations */ class I192 { /** * Constructor * @param value A string, number, or Decimal value */ constructor(value) { if (typeof value === "string" || typeof value === "number") { this.value = new decimal_js_1.Decimal(value); } else { this.value = value; } // Truncate to 18 decimal places to ensure precise representation this.value = this.truncateToDecimals(this.value); // Ensure value is within I192 range this.checkRange(); } /** * Truncate a value to exactly 18 decimal places (floor for positive, ceiling for negative) * This mimics Scrypto's behavior of truncation toward zero after each operation. * * Examples: * 123.4567890123456789123 -> 123.456789012345678900 (truncated) * -123.4567890123456789123 -> -123.456789012345678900 (truncated) */ truncateToDecimals(value) { // Multiply by 10^18, truncate to integer, then divide by 10^18 const multiplied = value.times(I192.DECIMAL_FACTOR); const truncated = value.isNegative() ? multiplied.ceil() // For negative numbers, ceil is truncation toward zero : multiplied.floor(); // For positive numbers, floor is truncation toward zero return truncated.dividedBy(I192.DECIMAL_FACTOR); } /** * Creates a new I192 instance from a value */ static from(value) { if (value instanceof I192) { return new I192(value.value); } return new I192(value); } /** * Creates an I192 with value 0 */ static zero() { return new I192(0); } /** * Creates an I192 with value 1 */ static one() { return new I192(1); } /** * Addition with intermediate truncation * * Both the input and the result are truncated to 18 decimal places, * mimicking Scrypto's behavior of truncating after each operation. */ add(other) { const otherValue = other instanceof I192 ? other.value : new decimal_js_1.Decimal(other); // Truncate the other value to 18 decimals first const truncatedOther = this.truncateToDecimals(otherValue); // Perform addition and truncate the result const result = this.truncateToDecimals(this.value.plus(truncatedOther)); return new I192(result); } /** * Subtraction with intermediate truncation * * Both the input and the result are truncated to 18 decimal places, * mimicking Scrypto's behavior of truncating after each operation. */ subtract(other) { const otherValue = other instanceof I192 ? other.value : new decimal_js_1.Decimal(other); // Truncate the other value to 18 decimals first const truncatedOther = this.truncateToDecimals(otherValue); // Perform subtraction and truncate the result const result = this.truncateToDecimals(this.value.minus(truncatedOther)); return new I192(result); } /** * Multiplication with intermediate truncation * * Both the input and the result are truncated to 18 decimal places, * mimicking Scrypto's behavior of truncating after each operation. */ multiply(other) { const otherValue = other instanceof I192 ? other.value : new decimal_js_1.Decimal(other); // Truncate the other value to 18 decimals first const truncatedOther = this.truncateToDecimals(otherValue); // Perform multiplication and truncate the result const result = this.truncateToDecimals(this.value.times(truncatedOther)); return new I192(result); } /** * Division with intermediate truncation * * Both the input and the result are truncated to 18 decimal places, * mimicking Scrypto's behavior of truncating after each operation. * * This operation is particularly sensitive to truncation, which can * cause different results compared to regular rounding methods. */ divide(other) { const otherValue = other instanceof I192 ? other.value : new decimal_js_1.Decimal(other); // Truncate the other value to 18 decimals first const truncatedOther = this.truncateToDecimals(otherValue); if (truncatedOther.isZero()) { throw new Error("Division by zero"); } // Perform division and truncate the result const result = this.truncateToDecimals(this.value.dividedBy(truncatedOther)); return new I192(result); } /** * Returns true if this value is greater than other */ greaterThan(other) { const otherValue = other instanceof I192 ? other.value : new decimal_js_1.Decimal(other); const truncatedOther = this.truncateToDecimals(otherValue); return this.value.greaterThan(truncatedOther); } /** * Returns true if this value is greater than or equal to other */ greaterThanOrEqualTo(other) { const otherValue = other instanceof I192 ? other.value : new decimal_js_1.Decimal(other); const truncatedOther = this.truncateToDecimals(otherValue); return this.value.greaterThanOrEqualTo(truncatedOther); } /** * Returns true if this value is less than other */ lessThan(other) { const otherValue = other instanceof I192 ? other.value : new decimal_js_1.Decimal(other); const truncatedOther = this.truncateToDecimals(otherValue); return this.value.lessThan(truncatedOther); } /** * Returns true if this value is less than or equal to other */ lessThanOrEqualTo(other) { const otherValue = other instanceof I192 ? other.value : new decimal_js_1.Decimal(other); const truncatedOther = this.truncateToDecimals(otherValue); return this.value.lessThanOrEqualTo(truncatedOther); } /** * Returns true if this value is equal to other */ equals(other) { const otherValue = other instanceof I192 ? other.value : new decimal_js_1.Decimal(other); const truncatedOther = this.truncateToDecimals(otherValue); return this.value.equals(truncatedOther); } /** * Returns true if this value is zero */ isZero() { return this.value.isZero(); } /** * Returns true if this value is negative */ isNegative() { return this.value.isNegative(); } /** * Returns true if this value is positive */ isPositive() { return this.value.isPositive(); } /** * Returns a string representation with full 18 decimal places * Format matches Scrypto Decimal's exact precision */ toString() { // Use decimal.js toFixed to get exact decimal precision // toFixed returns a string with the exact number of decimal places const stringValue = this.value.toFixed(I192.DECIMALS); return stringValue; } /** * Returns the decimal value */ toDecimal() { return new decimal_js_1.Decimal(this.value); } /** * Ensures the value is within the valid I192 range * Throws an error if out of range */ checkRange() { if (this.value.greaterThan(I192.MAX_VALUE)) { throw new Error("I192 overflow"); } if (this.value.lessThan(I192.MIN_VALUE)) { throw new Error("I192 underflow"); } } } exports.I192 = I192; // Constants I192.DECIMALS = 18; I192.DECIMAL_FACTOR = new decimal_js_1.Decimal(10).pow(I192.DECIMALS); // Maximum and minimum values for I192 (as per Scrypto's Decimal) // Max: 3138550867693340381917894711603833208051.177722232017256447 // Min: -3138550867693340381917894711603833208051.177722232017256448 I192.MAX_VALUE = new decimal_js_1.Decimal("3138550867693340381917894711603833208051.177722232017256447"); I192.MIN_VALUE = new decimal_js_1.Decimal("-3138550867693340381917894711603833208051.177722232017256448");