"use strict";
var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.priceToTickPrice = exports.feeTierToTickSpacing = exports.getLow = exports.getHigh = exports.round = exports.logWithBase = exports.tickToPrice = exports.getTickIdXRaw = exports.getTickFromPrice = exports.tokensForStrategy = exports.liquidityForStrategy = exports.MAX_PRICE = exports.MIN_PRICE = void 0;
exports.MIN_PRICE = Math.pow(1.0001, -887220);
exports.MAX_PRICE = Math.pow(1.0001, 887220);
// Calculate the liquidity share for a strategy based on the number of tokens owned
var liquidityForStrategy = function (price, low, high, tokens0, tokens1, decimal0, decimal1) {
    var decimal = decimal1 - decimal0;
    var lowHigh = [
        Math.sqrt(low * Math.pow(10, decimal)) * Math.pow(2, 96),
        Math.sqrt(high * Math.pow(10, decimal)) * Math.pow(2, 96),
    ];
    var sPrice = Math.sqrt(price * Math.pow(10, decimal)) * Math.pow(2, 96);
    var sLow = Math.min.apply(Math, __spreadArray([], __read(lowHigh), false));
    var sHigh = Math.max.apply(Math, __spreadArray([], __read(lowHigh), false));
    if (sPrice <= sLow) {
        return (tokens0 /
            ((Math.pow(2, 96) * (sHigh - sLow)) /
                sHigh /
                sLow /
                Math.pow(10, decimal0)));
    }
    else if (sPrice < sHigh && sPrice > sLow) {
        var liq0 = tokens0 /
            ((Math.pow(2, 96) * (sHigh - sPrice)) /
                sHigh /
                sPrice /
                Math.pow(10, decimal0));
        var liq1 = tokens1 / ((sPrice - sLow) / Math.pow(2, 96) / Math.pow(10, decimal1));
        return Math.min(liq1, liq0);
    }
    else {
        return (tokens1 / ((sHigh - sLow) / Math.pow(2, 96) / Math.pow(10, decimal1)));
    }
};
exports.liquidityForStrategy = liquidityForStrategy;
// Calculate the number of Tokens a strategy owns at a specific price
var tokensForStrategy = function (minRange, maxRange, investment, price, decimal) {
    if (price === void 0) { price = 0; }
    if (decimal === void 0) { decimal = 0; }
    var sqrtPrice = Math.sqrt(price * Math.pow(10, decimal));
    var sqrtLow = Math.sqrt(minRange * Math.pow(10, decimal));
    var sqrtHigh = Math.sqrt(maxRange * Math.pow(10, decimal));
    var delta, amount0, amount1;
    if (sqrtPrice > sqrtLow && sqrtPrice < sqrtHigh) {
        delta =
            investment /
                (sqrtPrice -
                    sqrtLow +
                    (1 / sqrtPrice - 1 / sqrtHigh) * (price * Math.pow(10, decimal)));
        amount1 = delta * (sqrtPrice - sqrtLow);
        amount0 = delta * (1 / sqrtPrice - 1 / sqrtHigh) * Math.pow(10, decimal);
    }
    else if (sqrtPrice <= sqrtLow) {
        delta = investment / ((1 / sqrtLow - 1 / sqrtHigh) * price);
        amount1 = 0;
        amount0 = delta * (1 / sqrtLow - 1 / sqrtHigh);
    }
    else {
        delta = investment / (sqrtHigh - sqrtLow);
        amount1 = delta * (sqrtHigh - sqrtLow);
        amount0 = 0;
    }
    // returns [quote, base] aka [x, y]
    return [amount0, amount1];
};
exports.tokensForStrategy = tokensForStrategy;
// calculate the liquidity tick at a specified price
var getTickFromPrice = function (_price, tickSpacing, // creating ranges has to happen according to tick spacing
quoteDec, // quote dec
baseDec // base dec
) {
    if (tickSpacing === void 0) { tickSpacing = 1; }
    if (quoteDec === void 0) { quoteDec = 0; }
    if (baseDec === void 0) { baseDec = 0; }
    var tickIDXRaw = (0, exports.getTickIdXRaw)(_price, quoteDec, baseDec);
    var tickWSpacing = Math.round(tickIDXRaw / tickSpacing) * tickSpacing;
    return (0, exports.round)(tickWSpacing, 0);
};
exports.getTickFromPrice = getTickFromPrice;
// calculate the liquidity tick at a specified price
var getTickIdXRaw = function (_price, quoteDec, // quote dec
baseDec // base dec
) {
    if (quoteDec === void 0) { quoteDec = 0; }
    if (baseDec === void 0) { baseDec = 0; }
    var price = typeof _price == 'string' ? parseFloat(_price) : _price;
    var valToLog = price * Math.pow(10, quoteDec - baseDec);
    return (0, exports.logWithBase)(valToLog, 1.0001);
};
exports.getTickIdXRaw = getTickIdXRaw;
var tickToPrice = function (tick, baseDec, quoteDec) {
    if (baseDec === void 0) { baseDec = 0; }
    if (quoteDec === void 0) { quoteDec = 0; }
    return Math.pow(1.0001, tick) / Math.pow(10, baseDec - quoteDec);
};
exports.tickToPrice = tickToPrice;
var logWithBase = function (y, x) {
    return Math.log(y) / Math.log(x);
};
exports.logWithBase = logWithBase;
var round = function (number, decimalPlaces) {
    var factorOfTen = Math.pow(10, decimalPlaces);
    return Math.round(number * factorOfTen) / factorOfTen;
};
exports.round = round;
var getHigh = function (price, x, y, low) {
    var sP = Math.sqrt(price);
    var sLow = Math.sqrt(low);
    var sHigh = (sP * y) / (x * sLow * sP - sP * sP * x + y);
    return sHigh * sHigh;
};
exports.getHigh = getHigh;
var getLow = function (price, x, y, high) {
    var sP = Math.sqrt(price);
    var sHigh = Math.sqrt(high);
    var sLow = y / (sHigh * x) + sP - y / (sP * x);
    return sLow * sLow;
};
exports.getLow = getLow;
exports.feeTierToTickSpacing = {
    100: 1,
    500: 10,
    3000: 60,
    10000: 200,
};
var priceToTickPrice = function (price, options) {
    if (options.feeTier) {
        return (0, exports.tickToPrice)((0, exports.getTickFromPrice)(price, exports.feeTierToTickSpacing[options.feeTier]));
    }
    else {
        return (0, exports.tickToPrice)((0, exports.getTickFromPrice)(price, options.tickSpacing));
    }
};
exports.priceToTickPrice = priceToTickPrice;
//# sourceMappingURL=uniV3Utils.js.map