"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isBorrowingEnabled = exports.getExpectedTokenBalanceAfterBorrow = void 0;
exports.isFlashLoanEnabled = isFlashLoanEnabled;
exports.determineFlashBorrowType = determineFlashBorrowType;
const bn_js_1 = __importDefault(require("bn.js"));
const classes_1 = require("../classes");
const utils_1 = require("../utils");
const getExpectedTokenBalanceAfterBorrow = async (rpc, mint, owner, amountToBorrowLamports, amountToBorrowMintDecimals) => {
    const initialUserTokenABalance = await (0, utils_1.getTokenAccountBalanceDecimal)(rpc, mint, owner);
    return initialUserTokenABalance
        .add((0, classes_1.lamportsToNumberDecimal)(amountToBorrowLamports, amountToBorrowMintDecimals))
        .toDecimalPlaces(amountToBorrowMintDecimals);
};
exports.getExpectedTokenBalanceAfterBorrow = getExpectedTokenBalanceAfterBorrow;
const isBorrowingEnabled = (reserve) => {
    return reserve.state.config.borrowLimit.gt(new bn_js_1.default(0));
};
exports.isBorrowingEnabled = isBorrowingEnabled;
/**
 * Returns true if flash loans are enabled on this reserve.
 * Flash loans are disabled when flashLoanFeeSf === U64_MAX (sentinel value).
 * Note: getFlashLoanFee() returns 0 for both "free" and "disabled", so we check the raw field.
 */
function isFlashLoanEnabled(reserve) {
    return reserve.state.config.fees.flashLoanFeeSf.toString() !== utils_1.U64_MAX;
}
/**
 * Determines which token to flash borrow based on reserve capabilities.
 *
 * Checks:
 * 1. Whether flash loans are enabled on the reserve (flashLoanFeeSf !== U64_MAX)
 * 2. Whether the reserve has sufficient available liquidity to service the flash borrow AND,
 *    on a withdraw/close, the collateral redeem that happens in the same transaction.
 *
 * Coll-flash and the collateral redeem (WithdrawObligationCollateralAndRedeemReserveCollateral)
 * both draw from the collateral reserve within a single transaction, and the flash loan is not
 * repaid until after the redeem. So a thin collateral reserve can satisfy the flash borrow alone
 * yet still revert with InsufficientLiquidity (klend 6008) once the redeem is added on top.
 *
 * `redeemCollateralLamports` is required (not optional): every caller must pass the collateral that
 * its transaction redeems from the collateral reserve in the same tx, so coll-flash viability always
 * accounts for both legs. Pass 0 only when the op genuinely has no redeem (opens / leverage-up
 * deposits). Withdraw/close, deleverage (adjust-decrease) and repay-with-collateral all redeem.
 *
 * @param collReserve - The collateral reserve
 * @param debtReserve - The debt reserve
 * @param requiredCollLamports - Amount needed if flash borrowing collateral
 * @param requiredDebtLamports - Amount needed if flash borrowing debt
 * @param redeemCollateralLamports - Collateral liquidity redeemed from the collateral reserve in the
 *   same tx (the coll withdraw/redeem amount). 0 only when the op has no redeem leg. Coll-flash
 *   requires the reserve to cover `requiredCollLamports + redeemCollateralLamports`.
 * @returns 'coll' or 'debt'
 * @throws if neither reserve supports flash borrowing the required amount
 */
function determineFlashBorrowType(collReserve, debtReserve, requiredCollLamports, requiredDebtLamports, redeemCollateralLamports) {
    const collEnabled = isFlashLoanEnabled(collReserve);
    const debtEnabled = isFlashLoanEnabled(debtReserve);
    const collLiquidity = collReserve.getLiquidityAvailableAmount();
    const debtLiquidity = debtReserve.getLiquidityAvailableAmount();
    // Coll-flash must leave enough liquidity for the in-tx collateral redeem too, not just the
    // flash borrow — otherwise the two collide and the redeem reverts (klend 6008).
    const requiredCollTotal = requiredCollLamports.add(redeemCollateralLamports);
    const collViable = collEnabled && collLiquidity.gte(requiredCollTotal);
    const debtViable = debtEnabled && debtLiquidity.gte(requiredDebtLamports);
    // Prefer the flash type the relevant reserve(s) can actually service. The old "always prefer
    // collateral" heuristic is wrong for thin/nascent LST reserves on withdraw/close: there the
    // collateral reserve is the constraint, so debt-flash (deep debt reserve) is the safe choice.
    if (collViable)
        return 'coll';
    if (debtViable)
        return 'debt';
    throw new Error(`Neither collateral nor debt reserve supports flash borrowing the required amount. ` +
        `Coll: enabled=${collEnabled}, available=${collLiquidity}, required=${requiredCollLamports}` +
        `${redeemCollateralLamports.gt(0) ? ` (+${redeemCollateralLamports} redeem = ${requiredCollTotal})` : ''}. ` +
        `Debt: enabled=${debtEnabled}, available=${debtLiquidity}, required=${requiredDebtLamports}.`);
}
//# sourceMappingURL=utils.js.map