"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UniV3Range = void 0;
var uniV3Utils_1 = require("./uniV3Utils");
var FEE = 0.003;
var UniV3Range = /** @class */ (function () {
    function UniV3Range(mm, value, minRange, maxRange, base, quote, liquidity, price) {
        var _this = this;
        this.mm = mm;
        this.value = value;
        this.minRange = minRange;
        this.maxRange = maxRange;
        this.updateContractParams = function () {
            var _a = _this, mm = _a.mm, minRange = _a.minRange, maxRange = _a.maxRange, base = _a.base, quote = _a.quote;
            var feeTier = mm.feeTier, reverse = mm.reverse, dec0 = mm.dec0, dec1 = mm.dec1, price = mm.price;
            var tickSpacing = uniV3Utils_1.feeTierToTickSpacing[feeTier];
            var min = reverse ? 1 / maxRange : minRange;
            var max = reverse ? 1 / minRange : maxRange;
            var dec = [dec0, dec1];
            if (reverse)
                dec.reverse;
            _this.lowerTick = (0, uniV3Utils_1.getTickFromPrice)(min, tickSpacing, dec[0], dec[1]);
            _this.upperTick = (0, uniV3Utils_1.getTickFromPrice)(max, tickSpacing, dec[0], dec[1]);
            var poolPrice = reverse ? 1 / price : price;
            var t0 = reverse ? quote : base;
            var t1 = reverse ? base : quote;
            var lp = (0, uniV3Utils_1.liquidityForStrategy)(poolPrice, (0, uniV3Utils_1.tickToPrice)(_this.lowerTick, dec0, dec1), (0, uniV3Utils_1.tickToPrice)(_this.upperTick, dec0, dec1), t0, t1, dec[0], dec[1]);
            _this.liquidity = Math.floor(lp).toLocaleString('fullwide', {
                useGrouping: false,
            });
        };
        price = price == null ? mm.price : price;
        // this is when we initialize from on-chain data
        if (base != null && quote != null) {
            this.base = base;
            this.quote = quote;
            this.updateContractParams();
            console.log('lp', this.liquidity, 'vs', liquidity);
            if (liquidity != null)
                this.liquidity = liquidity;
            return;
        }
        // this is when we initialize from rebalance params
        var tokens = (0, uniV3Utils_1.tokensForStrategy)(this.minRange, this.maxRange, this.value, price, 0);
        if (value < 0)
            throw new Error('value must be positive');
        // base token is allways first
        this.base = tokens[0];
        this.quote = tokens[1];
        this.updateContractParams();
    }
    UniV3Range.prototype.dTokensAtPrice = function (startPrice, price) {
        var _a = this, minRange = _a.minRange, maxRange = _a.maxRange, base = _a.base, quote = _a.quote;
        var L = (0, uniV3Utils_1.liquidityForStrategy)(startPrice, minRange, maxRange, base, quote, 0, 0);
        if (price > maxRange)
            price = maxRange;
        if (price < minRange)
            price = minRange;
        var dBase = (1 / Math.sqrt(price) - 1 / Math.sqrt(startPrice)) * L;
        var dQuote = (Math.sqrt(price) - Math.sqrt(startPrice)) * L;
        return { dBase: dBase, dQuote: dQuote };
    };
    // @dev returns updated price and amounts for new swaps if
    // we went outside the range
    UniV3Range.prototype.simulateSwap = function (swap, startPrice, useBase) {
        if (useBase === void 0) { useBase = false; }
        var swapBase = swap.dBase;
        var swapQuote = swap.dQuote;
        var fees = {
            base: swapBase <= 0 ? 0 : swapBase * FEE,
            quote: swapQuote <= 0 ? 0 : swapQuote * FEE,
        };
        if (startPrice < this.minRange || startPrice > this.maxRange)
            throw new Error('start price is outside of range');
        var L = (0, uniV3Utils_1.liquidityForStrategy)(startPrice, this.minRange, this.maxRange, this.base, this.quote, 0, 0);
        var dQ = swapQuote - fees.quote;
        var dB = swapBase - fees.base;
        // sDP is either Δ√P or Δ(1/√P)
        var sDP = swapBase > 0 || useBase ? dB / L : dQ / L;
        var newPrice = swapBase > 0 || useBase
            ? 1 / Math.pow((sDP + Math.sqrt(1 / startPrice)), 2)
            : Math.pow((sDP + Math.sqrt(startPrice)), 2);
        var price = newPrice > this.maxRange
            ? this.maxRange
            : newPrice < this.minRange
                ? this.minRange
                : newPrice;
        var outsideOfRange = newPrice !== price;
        var swappedBase = (1 / Math.sqrt(price) - 1 / Math.sqrt(startPrice)) * L;
        var swappedQuote = (Math.sqrt(price) - Math.sqrt(startPrice)) * L;
        var dBase = newPrice == price || swapBase <= 0 ? 0 : swapBase - swappedBase;
        var dQuote = newPrice == price || swapQuote <= 0 ? 0 : swapQuote - swappedQuote;
        var base = this.base + swappedBase;
        var quote = this.quote + swappedQuote;
        // adjust fees for actual amount swapped
        fees = {
            base: swapBase <= 0 ? 0 : (swappedBase / (1 - FEE)) * FEE,
            quote: swapQuote <= 0 ? 0 : (swappedQuote / (1 - FEE)) * FEE,
        };
        return {
            dBase: dBase,
            dQuote: dQuote,
            price: price,
            outsideOfRange: outsideOfRange,
            fees: fees,
            quote: quote,
            base: base,
            swappedQuote: swappedQuote,
            swappedBase: swappedBase,
        };
    };
    return UniV3Range;
}());
exports.UniV3Range = UniV3Range;
//# sourceMappingURL=uniV3Range.js.map