"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeTokenName = exports.getDefaultConfigParams = exports.DebtConfig = exports.CollateralConfig = exports.AssetReserveConfigCli = exports.AssetReserveConfig = void 0;
exports.getReserveOracleConfigs = getReserveOracleConfigs;
exports.parseOracleType = parseOracleType;
const types_1 = require("../@codegen/klend/types");
const decimal_js_1 = __importDefault(require("decimal.js"));
const classes_1 = require("../classes");
const bn_js_1 = __importDefault(require("bn.js"));
const classes_2 = require("../classes");
const pubkey_1 = require("./pubkey");
const scope_sdk_1 = require("@kamino-finance/scope-sdk");
const types_2 = require("@kamino-finance/scope-sdk/dist/@codegen/scope/types");
class AssetReserveConfig {
    mint;
    tokenName;
    mintDecimals;
    mintTokenProgram;
    assetReserveConfigParams;
    constructor(fields) {
        this.mint = fields.mint;
        this.tokenName = fields.tokenName;
        this.mintDecimals = fields.mintDecimals;
        this.mintTokenProgram = fields.mintTokenProgram;
        // TODO: verify defaults and ensure opinionated
        this.assetReserveConfigParams = (0, exports.getDefaultConfigParams)();
        this.assetReserveConfigParams.priceFeed = fields.priceFeed;
        this.assetReserveConfigParams.loanToValuePct = fields.loanToValuePct;
        this.assetReserveConfigParams.liquidationThresholdPct = fields.liquidationThresholdPct;
        this.assetReserveConfigParams.borrowRateCurve = fields.borrowRateCurve;
        this.assetReserveConfigParams.depositLimit = fields.depositLimit;
        this.assetReserveConfigParams.borrowLimit = fields.borrowLimit;
    }
    setAssetConfigParams(assetReserveConfigParams) {
        this.assetReserveConfigParams = assetReserveConfigParams;
    }
    getReserveConfig() {
        return buildReserveConfig({
            configParams: this.assetReserveConfigParams,
            mintDecimals: this.mintDecimals,
            tokenName: this.tokenName,
        });
    }
}
exports.AssetReserveConfig = AssetReserveConfig;
class AssetReserveConfigCli {
    mint;
    tokenName;
    mintDecimals;
    mintTokenProgram;
    reserveConfig;
    assetReserveConfigParams;
    constructor(mint, mintTokenProgram, reserveConfig) {
        this.reserveConfig = reserveConfig;
        this.tokenName = '';
        this.mintDecimals = 0;
        this.assetReserveConfigParams = (0, exports.getDefaultConfigParams)();
        this.mint = mint;
        this.mintTokenProgram = mintTokenProgram;
    }
    setAssetConfigParams(assetReserveConfigParams) {
        this.assetReserveConfigParams = assetReserveConfigParams;
    }
    setReserveConfig(reserveConfig) {
        this.reserveConfig = reserveConfig;
    }
    getReserveConfig() {
        return this.reserveConfig
            ? this.reserveConfig
            : buildReserveConfig({
                configParams: this.assetReserveConfigParams,
                mintDecimals: this.mintDecimals,
                tokenName: this.tokenName,
            });
    }
}
exports.AssetReserveConfigCli = AssetReserveConfigCli;
class CollateralConfig {
    mint;
    tokenName;
    mintDecimals;
    mintTokenProgram;
    assetReserveConfigParams;
    constructor(fields) {
        this.mint = fields.mint;
        this.tokenName = fields.tokenName;
        this.mintDecimals = fields.mintDecimals;
        this.mintTokenProgram = fields.mintTokenProgram;
        // TODO: verify defaults and ensure opinionated
        this.assetReserveConfigParams = (0, exports.getDefaultConfigParams)();
        this.assetReserveConfigParams.priceFeed = fields.priceFeed;
        this.assetReserveConfigParams.loanToValuePct = fields.loanToValuePct;
        this.assetReserveConfigParams.liquidationThresholdPct = fields.liquidationThresholdPct;
        this.assetReserveConfigParams.borrowLimit = new decimal_js_1.default(0);
    }
    setAssetConfigParams(assetReserveConfigParams) {
        this.assetReserveConfigParams = assetReserveConfigParams;
    }
    getReserveConfig() {
        return buildReserveConfig({
            configParams: this.assetReserveConfigParams,
            mintDecimals: this.mintDecimals,
            tokenName: this.tokenName,
        });
    }
}
exports.CollateralConfig = CollateralConfig;
class DebtConfig {
    mint;
    tokenName;
    mintDecimals;
    mintTokenProgram;
    assetReserveConfigParams;
    borrowLimitOutsideElevationGroup;
    debtWithdrawalCapConfigCapacity;
    constructor(fields) {
        this.mint = fields.mint;
        this.tokenName = fields.tokenName;
        this.mintDecimals = fields.mintDecimals;
        this.mintTokenProgram = fields.mintTokenProgram;
        this.borrowLimitOutsideElevationGroup = fields.borrowLimitOutsideElevationGroup;
        this.debtWithdrawalCapConfigCapacity = fields.debtWithdrawalCapConfigCapacity;
        // TODO: verify defaults and ensure opinionated
        this.assetReserveConfigParams = (0, exports.getDefaultConfigParams)();
        this.assetReserveConfigParams.priceFeed = fields.priceFeed;
        this.assetReserveConfigParams.borrowRateCurve = fields.borrowRateCurve;
    }
    setAssetConfigParams(assetReserveConfigParams) {
        this.assetReserveConfigParams = assetReserveConfigParams;
    }
    getReserveConfig() {
        return buildReserveConfig({
            configParams: this.assetReserveConfigParams,
            mintDecimals: this.mintDecimals,
            tokenName: this.tokenName,
            borrowLimitOutsideElevationGroup: this.borrowLimitOutsideElevationGroup,
            debtWithdrawalCapConfigCapacity: this.debtWithdrawalCapConfigCapacity,
        });
    }
}
exports.DebtConfig = DebtConfig;
const getDefaultConfigParams = () => {
    return {
        loanToValuePct: 70,
        maxLiquidationBonusBps: 500,
        minLiquidationBonusBps: 200,
        badDebtLiquidationBonusBps: 10,
        liquidationThresholdPct: 75,
        originationFeeSf: classes_1.ZERO_FRACTION,
        flashLoanFeeSf: classes_1.ZERO_FRACTION,
        protocolTakeRate: 0,
        elevationGroups: new Array(20).fill(0),
        priceFeed: null,
        borrowLimit: new decimal_js_1.default(1000.0),
        depositLimit: new decimal_js_1.default(1000.0),
        borrowRateCurve: new types_1.BorrowRateCurve({
            points: [
                new types_1.CurvePoint({ utilizationRateBps: 0, borrowRateBps: 1000 }),
                new types_1.CurvePoint({ utilizationRateBps: 10000, borrowRateBps: 1000 }),
                ...Array(9).fill(new types_1.CurvePoint({ utilizationRateBps: 10000, borrowRateBps: 1000 })),
            ],
        }),
        maxAgePriceSeconds: 180,
        maxAgeTwapSeconds: 240,
    };
};
exports.getDefaultConfigParams = getDefaultConfigParams;
const encodeTokenName = (tokenName) => {
    const buffer = Buffer.alloc(32);
    const tokenNameEncoded = new Uint8Array(32);
    const s = new TextEncoder().encode(tokenName);
    tokenNameEncoded.set(s);
    for (let i = 0; i < tokenNameEncoded.length; i++) {
        buffer[i] = tokenNameEncoded[i];
    }
    return [...buffer];
};
exports.encodeTokenName = encodeTokenName;
function buildReserveConfig(fields) {
    const reserveConfigFields = {
        status: 0,
        loanToValuePct: fields.configParams.loanToValuePct,
        liquidationThresholdPct: fields.configParams.liquidationThresholdPct,
        minLiquidationBonusBps: fields.configParams.minLiquidationBonusBps,
        protocolLiquidationFeePct: 0,
        protocolOrderExecutionFeePct: 0,
        protocolTakeRatePct: fields.configParams.protocolTakeRate,
        paddingDeprecatedAssetTier: 0,
        maxLiquidationBonusBps: fields.configParams.maxLiquidationBonusBps,
        badDebtLiquidationBonusBps: fields.configParams.badDebtLiquidationBonusBps,
        fees: {
            originationFeeSf: fields.configParams.originationFeeSf.getValue(),
            flashLoanFeeSf: fields.configParams.flashLoanFeeSf.getValue(),
            padding: Array(6).fill(0),
        },
        depositLimit: new bn_js_1.default((0, classes_2.numberToLamportsDecimal)(fields.configParams.depositLimit, fields.mintDecimals).floor().toString()),
        borrowLimit: new bn_js_1.default((0, classes_2.numberToLamportsDecimal)(fields.configParams.borrowLimit, fields.mintDecimals).floor().toString()),
        tokenInfo: {
            name: (0, exports.encodeTokenName)(fields.tokenName),
            heuristic: new types_1.PriceHeuristic({
                lower: new bn_js_1.default(0),
                upper: new bn_js_1.default(0),
                exp: new bn_js_1.default(0),
            }),
            maxTwapDivergenceBps: new bn_js_1.default(0),
            maxAgePriceSeconds: new bn_js_1.default(fields.configParams.maxAgePriceSeconds),
            maxAgeTwapSeconds: new bn_js_1.default(fields.configParams.maxAgeTwapSeconds),
            ...getReserveOracleConfigs(fields.configParams.priceFeed),
            padding: Array(20).fill(new bn_js_1.default(0)),
        },
        borrowRateCurve: fields.configParams.borrowRateCurve,
        depositWithdrawalCap: new types_1.WithdrawalCaps({
            configCapacity: new bn_js_1.default((0, classes_2.numberToLamportsDecimal)(fields.configParams.depositLimit ?? new decimal_js_1.default(0), fields.mintDecimals)
                .floor()
                .toString()),
            currentTotal: new bn_js_1.default(0),
            lastIntervalStartTimestamp: new bn_js_1.default(0),
            configIntervalLengthSeconds: new bn_js_1.default(0),
        }),
        debtWithdrawalCap: new types_1.WithdrawalCaps({
            configCapacity: new bn_js_1.default((0, classes_2.numberToLamportsDecimal)(fields.debtWithdrawalCapConfigCapacity ?? new decimal_js_1.default(0), fields.mintDecimals)
                .floor()
                .toString()),
            currentTotal: new bn_js_1.default(0),
            lastIntervalStartTimestamp: new bn_js_1.default(0),
            configIntervalLengthSeconds: new bn_js_1.default(0),
        }),
        deleveragingMarginCallPeriodSecs: new bn_js_1.default(0),
        borrowFactorPct: new bn_js_1.default(100),
        elevationGroups: fields.configParams.elevationGroups,
        deleveragingThresholdDecreaseBpsPerDay: new bn_js_1.default(24),
        disableUsageAsCollOutsideEmode: 0,
        utilizationLimitBlockBorrowingAbovePct: 0,
        hostFixedInterestRateBps: 0,
        autodeleverageEnabled: 0,
        borrowLimitOutsideElevationGroup: new bn_js_1.default((0, classes_2.numberToLamportsDecimal)(fields.borrowLimitOutsideElevationGroup ?? new decimal_js_1.default(0), fields.mintDecimals)
            .floor()
            .toString()),
        borrowLimitAgainstThisCollateralInElevationGroup: Array(32).fill(new bn_js_1.default(0)),
        deleveragingBonusIncreaseBpsPerDay: new bn_js_1.default(100),
        reserved1: Array(1).fill(0),
        minDeleveragingBonusBps: 0,
        proposerAuthorityLocked: 0,
        blockCtokenUsage: 0,
        debtMaturityTimestamp: new bn_js_1.default(0),
        debtTermSeconds: new bn_js_1.default(0),
        earlyRepayRemainingInterestPct: 0,
        emergencyMode: 0,
        rewardsAmountPerSlot: new bn_js_1.default(0),
    };
    return new types_1.ReserveConfig(reserveConfigFields);
}
function getReserveOracleConfigs(priceFeed) {
    let pythConfiguration = new types_1.PythConfiguration({
        price: pubkey_1.NULL_PUBKEY,
    });
    let switchboardConfiguration = new types_1.SwitchboardConfiguration({
        priceAggregator: pubkey_1.NULL_PUBKEY,
        twapAggregator: pubkey_1.NULL_PUBKEY,
    });
    let scopeConfiguration = new types_1.ScopeConfiguration({
        priceFeed: pubkey_1.NULL_PUBKEY,
        priceChain: [65535, 65535, 65535, 65535],
        twapChain: [65535, 65535, 65535, 65535],
    });
    if (priceFeed) {
        const { scopePriceConfigAddress, scopeChain, scopeTwapChain, pythPrice, switchboardPrice, switchboardTwapPrice } = priceFeed;
        if (pythPrice) {
            pythConfiguration = new types_1.PythConfiguration({ price: pythPrice });
        }
        if (switchboardPrice) {
            switchboardConfiguration = new types_1.SwitchboardConfiguration({
                priceAggregator: switchboardPrice ? switchboardPrice : pubkey_1.NULL_PUBKEY,
                twapAggregator: switchboardTwapPrice ? switchboardTwapPrice : pubkey_1.NULL_PUBKEY,
            });
        }
        if (scopePriceConfigAddress) {
            scopeConfiguration = new types_1.ScopeConfiguration({
                priceFeed: scopePriceConfigAddress,
                priceChain: scopeChain.concat(Array(4 - scopeChain.length).fill(scope_sdk_1.U16_MAX)),
                twapChain: scopeTwapChain.concat(Array(4 - scopeTwapChain.length).fill(scope_sdk_1.U16_MAX)),
            });
        }
    }
    return {
        pythConfiguration,
        switchboardConfiguration,
        scopeConfiguration,
    };
}
const ORACLE_TYPE_MAP = Object.fromEntries(Object.values(types_2.OracleType)
    // Filter for oracle types that have a discriminator property
    // This ensures we only include actual oracle implementations in the mapping
    // Pyth is used as a type assertion here but actually any oracle type with a discriminator will pass
    .filter((T) => 'discriminator' in T)
    .map((T) => [T.discriminator, T.name]));
function parseOracleType(type) {
    return ORACLE_TYPE_MAP[type] || 'Unknown';
}
//# sourceMappingURL=managerTypes.js.map