"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.KyberswapElasticFarmContractPositionBuilder = void 0;
const common_1 = require("@nestjs/common");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const lodash_1 = require("lodash");
const app_toolkit_interface_1 = require("../../../app-toolkit/app-toolkit.interface");
const drill_balance_helper_1 = require("../../../app-toolkit/helpers/drill-balance.helper");
const display_item_present_1 = require("../../../app-toolkit/helpers/presentation/display-item.present");
const image_present_1 = require("../../../app-toolkit/helpers/presentation/image.present");
const contract_interface_1 = require("../../../position/contract.interface");
const position_interface_1 = require("../../../position/position.interface");
const position_utils_1 = require("../../../position/position.utils");
const contracts_1 = require("../contracts");
const kyberswap_elastic_liquidity_utils_1 = require("./kyberswap-elastic.liquidity.utils");
let KyberswapElasticFarmContractPositionBuilder = class KyberswapElasticFarmContractPositionBuilder {
    constructor(appToolkit, contractFactory) {
        this.appToolkit = appToolkit;
        this.contractFactory = contractFactory;
        this.managerAddress = '0x2b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8';
        this.factoryAddress = '0x5f1dddbf348ac2fbe22a163e30f99f9ece3dd50a';
    }
    buildPosition({ multicall, positionId, poolId, tokenLoader, network, collapseClaimable, kyberswapElasticLmAddress, }) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const positionManager = this.contractFactory.positionManager({ address: this.managerAddress, network });
            const factoryContract = this.contractFactory.factory({ address: this.factoryAddress, network });
            const elasticLmContract = this.contractFactory.kyberswapElasticLm({ address: kyberswapElasticLmAddress, network });
            const position = yield multicall.wrap(positionManager).positions(positionId);
            const fee = (_a = position.info) === null || _a === void 0 ? void 0 : _a.fee;
            const poolInfo = yield multicall.wrap(elasticLmContract).getPoolInfo(poolId);
            const rewardTokenAddresses = poolInfo.rewardTokens.map(x => x.toLowerCase());
            const token0Address = position.info.token0.toLowerCase();
            const token1Address = position.info.token1.toLowerCase();
            const queries = [token0Address, token1Address, ...rewardTokenAddresses].map(t => ({ address: t, network }));
            const [token0, token1, claimableToken] = yield tokenLoader.getMany(queries);
            if (!token0 || !token1 || !claimableToken)
                return null;
            const poolAddr = yield multicall.wrap(factoryContract).getPool(token0Address, token1Address, fee);
            const poolAddress = poolAddr.toLowerCase();
            const poolContract = this.contractFactory.pool({ address: poolAddress, network });
            const token0Contract = this.contractFactory.erc20(token0);
            const token1Contract = this.contractFactory.erc20(token1);
            const [liquidityState, poolState, positionClaimables, reserveRaw0, reserveRaw1] = yield Promise.all([
                multicall.wrap(poolContract).getLiquidityState(),
                multicall.wrap(poolContract).getPoolState(),
                multicall.wrap(elasticLmContract).getUserInfo(positionId, poolId),
                multicall.wrap(token0Contract).balanceOf(poolAddress),
                multicall.wrap(token1Contract).balanceOf(poolAddress),
            ]);
            const positionData = {
                tickLower: position.pos.tickLower,
                tickUpper: position.pos.tickUpper,
                liquidity: position.pos.liquidity,
                rTokenOwed: position.pos.rTokenOwed,
                feeGrowthInsideLast: position.pos.feeGrowthInsideLast,
                nonce: position.pos.nonce,
                operator: position.pos.operator,
                poolId: position.pos.poolId,
                token0: position.info.token0,
                token1: position.info.token1,
                fee: fee,
            };
            const state = {
                sqrtPriceX96: poolState.sqrtP,
                reinvestL: liquidityState.reinvestL,
                currentTick: poolState.currentTick,
                liquidity: liquidityState.baseL,
            };
            const range = (0, kyberswap_elastic_liquidity_utils_1.getRange)({ position: positionData, state, token0, token1, network });
            const suppliedBalances = (0, kyberswap_elastic_liquidity_utils_1.getSupplied)({ position: positionData, state, token0, token1, network });
            const suppliedTokens = [token0, token1].map(v => (0, position_utils_1.supplied)(v));
            const suppliedTokenBalances = suppliedTokens.map((t, i) => (0, drill_balance_helper_1.drillBalance)(t, suppliedBalances[i]));
            const claimableTokens = [claimableToken].map(v => (0, position_utils_1.claimable)(v));
            const claimablesBalance = positionClaimables.rewardPending.map(x => x.toString());
            const claimableTokenBalances = claimableTokens.map((t, i) => (0, drill_balance_helper_1.drillBalance)(t, claimablesBalance[i]));
            let tokens = [...suppliedTokenBalances, ...claimableTokenBalances].filter(t => t.balanceUSD > 0.01);
            const balanceUSD = (0, lodash_1.sumBy)(tokens, v => v.balanceUSD);
            const reservesRaw = [reserveRaw0, reserveRaw1];
            const reserves = reservesRaw.map((r, i) => Number(r) / Math.pow(10, suppliedTokens[i].decimals));
            const totalLiquidity = reserves[0] * suppliedTokens[0].price + reserves[1] * suppliedTokens[1].price;
            if (collapseClaimable) {
                tokens = [token0, token1].map((t, i) => (0, drill_balance_helper_1.drillBalance)(t, new bignumber_js_1.default(suppliedBalances[i]).plus(claimablesBalance[i]).toFixed(0)));
            }
            const feeTier = Number(fee) / Math.pow(10, 4);
            const dataProps = {
                feeTier,
                rangeStart: range[0],
                rangeEnd: range[1],
                liquidity: totalLiquidity,
                reserves: reserves,
                poolAddress: poolAddr.toLowerCase(),
                assetStandard: position_interface_1.Standard.ERC_721,
                positionKey: `${feeTier}`,
            };
            const displayProps = {
                label: `${token0.symbol} / ${token1.symbol} (${range[0]} to ${range[1]})`,
                images: [...(0, image_present_1.getImagesFromToken)(token0), ...(0, image_present_1.getImagesFromToken)(token1)],
                statsItems: [{ label: 'Liquidity', value: (0, display_item_present_1.buildDollarDisplayItem)(Number(state.liquidity)) }],
            };
            const balance = {
                type: contract_interface_1.ContractType.POSITION,
                address: this.managerAddress,
                appId: 'kyberswap',
                groupId: 'farm',
                network,
                tokens,
                dataProps,
                displayProps,
                balanceUSD,
            };
            balance.key = this.appToolkit.getPositionKey(balance);
            return balance;
        });
    }
};
KyberswapElasticFarmContractPositionBuilder = __decorate([
    __param(0, (0, common_1.Inject)(app_toolkit_interface_1.APP_TOOLKIT)),
    __param(1, (0, common_1.Inject)(contracts_1.KyberswapElasticContractFactory)),
    __metadata("design:paramtypes", [Object, contracts_1.KyberswapElasticContractFactory])
], KyberswapElasticFarmContractPositionBuilder);
exports.KyberswapElasticFarmContractPositionBuilder = KyberswapElasticFarmContractPositionBuilder;
//# sourceMappingURL=kyberswap-elastic.farm.contract-position-builder.js.map