"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LendingObligationFixedRate = exports.LendingObligation = exports.LeverageObligationFixedRate = exports.LeverageObligation = exports.MultiplyObligationFixedRate = exports.MultiplyObligation = exports.VanillaObligation = exports.ObligationTypeTag = void 0;
exports.getObligationPdaWithArgs = getObligationPdaWithArgs;
exports.getObligationType = getObligationType;
exports.getObligationTypeFromObligation = getObligationTypeFromObligation;
const kit_1 = require("@solana/kit");
const pubkey_1 = require("./pubkey");
const addressEncoder = (0, kit_1.getAddressEncoder)();
var ObligationTypeTag;
(function (ObligationTypeTag) {
    ObligationTypeTag[ObligationTypeTag["Vanilla"] = 0] = "Vanilla";
    ObligationTypeTag[ObligationTypeTag["Multiply"] = 1] = "Multiply";
    ObligationTypeTag[ObligationTypeTag["Lending"] = 2] = "Lending";
    ObligationTypeTag[ObligationTypeTag["Leverage"] = 3] = "Leverage";
    ObligationTypeTag[ObligationTypeTag["MultiplyFixedRate"] = 4] = "MultiplyFixedRate";
    ObligationTypeTag[ObligationTypeTag["LendingFixedRate"] = 5] = "LendingFixedRate";
    ObligationTypeTag[ObligationTypeTag["LeverageFixedRate"] = 6] = "LeverageFixedRate";
})(ObligationTypeTag || (exports.ObligationTypeTag = ObligationTypeTag = {}));
class VanillaObligation {
    programId;
    id;
    static tag = 0;
    constructor(programId, id) {
        this.programId = programId;
        this.id = id ?? 0;
    }
    toArgs() {
        const initObligationArgs = {
            tag: VanillaObligation.tag,
            id: this.id,
            seed1: pubkey_1.DEFAULT_PUBLIC_KEY,
            seed2: pubkey_1.DEFAULT_PUBLIC_KEY,
        };
        return initObligationArgs;
    }
    toPda(market, user) {
        return getObligationPdaWithArgs(market, user, this.toArgs(), this.programId);
    }
}
exports.VanillaObligation = VanillaObligation;
class MultiplyObligation {
    collToken;
    debtToken;
    programId;
    id;
    static tag = 1;
    constructor(collToken, debtToken, programId, id) {
        this.collToken = collToken;
        this.debtToken = debtToken;
        this.programId = programId;
        this.id = id ?? 0;
    }
    toArgs() {
        const initObligationArgs = {
            tag: MultiplyObligation.tag,
            id: this.id,
            seed1: this.collToken,
            seed2: this.debtToken,
        };
        return initObligationArgs;
    }
    toPda(market, user) {
        return getObligationPdaWithArgs(market, user, this.toArgs(), this.programId);
    }
}
exports.MultiplyObligation = MultiplyObligation;
class MultiplyObligationFixedRate {
    collReserveAddress;
    debtReserveAddress;
    programId;
    id;
    static tag = 4;
    constructor(collReserveAddress, debtReserveAddress, programId, id) {
        this.collReserveAddress = collReserveAddress;
        this.debtReserveAddress = debtReserveAddress;
        this.programId = programId;
        this.id = id ?? 0;
    }
    toArgs() {
        const initObligationArgs = {
            tag: MultiplyObligationFixedRate.tag,
            id: this.id,
            seed1: this.collReserveAddress,
            seed2: this.debtReserveAddress,
        };
        return initObligationArgs;
    }
    toPda(market, user) {
        return getObligationPdaWithArgs(market, user, this.toArgs(), this.programId);
    }
}
exports.MultiplyObligationFixedRate = MultiplyObligationFixedRate;
class LeverageObligation {
    collToken;
    debtToken;
    programId;
    id;
    static tag = 3;
    constructor(collToken, debtToken, programId, id) {
        this.collToken = collToken;
        this.debtToken = debtToken;
        this.programId = programId;
        this.id = id ?? 0;
    }
    toArgs() {
        const initObligationArgs = {
            tag: LeverageObligation.tag,
            id: this.id,
            seed1: this.collToken,
            seed2: this.debtToken,
        };
        return initObligationArgs;
    }
    toPda(market, user) {
        return getObligationPdaWithArgs(market, user, this.toArgs(), this.programId);
    }
}
exports.LeverageObligation = LeverageObligation;
class LeverageObligationFixedRate {
    collReserveAddress;
    debtReserveAddress;
    programId;
    id;
    static tag = 6;
    constructor(collReserveAddress, debtReserveAddress, programId, id) {
        this.collReserveAddress = collReserveAddress;
        this.debtReserveAddress = debtReserveAddress;
        this.programId = programId;
        this.id = id ?? 0;
    }
    toArgs() {
        const initObligationArgs = {
            tag: LeverageObligationFixedRate.tag,
            id: this.id,
            seed1: this.collReserveAddress,
            seed2: this.debtReserveAddress,
        };
        return initObligationArgs;
    }
    toPda(market, user) {
        return getObligationPdaWithArgs(market, user, this.toArgs(), this.programId);
    }
}
exports.LeverageObligationFixedRate = LeverageObligationFixedRate;
class LendingObligation {
    token;
    programId;
    id;
    static tag = 2;
    constructor(token, programId, id) {
        this.token = token;
        this.programId = programId;
        this.id = id ?? 0;
    }
    toArgs() {
        const initObligationArgs = {
            tag: LendingObligation.tag,
            id: this.id,
            seed1: this.token,
            seed2: this.token,
        };
        return initObligationArgs;
    }
    toPda(market, user) {
        return getObligationPdaWithArgs(market, user, this.toArgs(), this.programId);
    }
}
exports.LendingObligation = LendingObligation;
class LendingObligationFixedRate {
    reserveAddress;
    programId;
    id;
    static tag = 5;
    constructor(reserveAddress, programId, id) {
        this.reserveAddress = reserveAddress;
        this.programId = programId;
        this.id = id ?? 0;
    }
    toArgs() {
        const initObligationArgs = {
            tag: LendingObligationFixedRate.tag,
            id: this.id,
            seed1: this.reserveAddress,
            seed2: this.reserveAddress,
        };
        return initObligationArgs;
    }
    toPda(market, user) {
        return getObligationPdaWithArgs(market, user, this.toArgs(), this.programId);
    }
}
exports.LendingObligationFixedRate = LendingObligationFixedRate;
async function getObligationPdaWithArgs(market, user, args, programId) {
    const seeds = [
        Buffer.from([args.tag]),
        Buffer.from([args.id]),
        addressEncoder.encode(user),
        addressEncoder.encode(market),
        addressEncoder.encode(args.seed1),
        addressEncoder.encode(args.seed2),
    ];
    const [obligationAddress, _obligationAddressBump] = await (0, kit_1.getProgramDerivedAddress)({
        seeds,
        programAddress: programId,
    });
    return obligationAddress;
}
/**
 * Resolves the {@link ObligationType} subclass for the given tag.
 *
 * **Reserve-addresses only** (a single mint can map to a float-rate reserve plus multiple
 * fixed-rate reserves — mint alone is ambiguous). Variable-rate tags (1/2/3) derive their
 * mint seeds from the supplied reserve address via {@link KaminoMarket.getExistingReserveByAddress};
 * fixed-rate tags (4/5/6) use the reserve address directly as the seed.
 *
 * @param reserveAddress1 deposit/collateral reserve. Required for every non-Vanilla tag.
 * @param reserveAddress2 borrow/debt reserve. Required for Multiply/Leverage (variable and fixed-rate).
 */
function getObligationType(kaminoMarket, obligationTag, reserveAddress1 = (0, kit_1.none)(), reserveAddress2 = (0, kit_1.none)()) {
    switch (obligationTag) {
        case VanillaObligation.tag: {
            return new VanillaObligation(kaminoMarket.programId);
        }
        case MultiplyObligation.tag: {
            if ((0, kit_1.isNone)(reserveAddress1)) {
                throw new Error('MultiplyObligation PDA requires reserve address 1 (collateral)');
            }
            if ((0, kit_1.isNone)(reserveAddress2)) {
                throw new Error('MultiplyObligation PDA requires reserve address 2 (debt)');
            }
            const collMint = kaminoMarket
                .getExistingReserveByAddress(reserveAddress1.value, 'Multiply collateral')
                .getLiquidityMint();
            const debtMint = kaminoMarket
                .getExistingReserveByAddress(reserveAddress2.value, 'Multiply debt')
                .getLiquidityMint();
            return new MultiplyObligation(collMint, debtMint, kaminoMarket.programId);
        }
        case LeverageObligation.tag: {
            if ((0, kit_1.isNone)(reserveAddress1)) {
                throw new Error('LeverageObligation PDA requires reserve address 1 (collateral)');
            }
            if ((0, kit_1.isNone)(reserveAddress2)) {
                throw new Error('LeverageObligation PDA requires reserve address 2 (debt)');
            }
            const collMint = kaminoMarket
                .getExistingReserveByAddress(reserveAddress1.value, 'Leverage collateral')
                .getLiquidityMint();
            const debtMint = kaminoMarket
                .getExistingReserveByAddress(reserveAddress2.value, 'Leverage debt')
                .getLiquidityMint();
            return new LeverageObligation(collMint, debtMint, kaminoMarket.programId);
        }
        case LendingObligation.tag: {
            if ((0, kit_1.isNone)(reserveAddress1)) {
                throw new Error('LendingObligation PDA requires reserve address');
            }
            const mint = kaminoMarket.getExistingReserveByAddress(reserveAddress1.value, 'Lending').getLiquidityMint();
            return new LendingObligation(mint, kaminoMarket.programId);
        }
        case LendingObligationFixedRate.tag: {
            if ((0, kit_1.isNone)(reserveAddress1)) {
                throw new Error('LendingObligationFixedRate PDA requires reserve address');
            }
            return new LendingObligationFixedRate(reserveAddress1.value, kaminoMarket.programId);
        }
        case MultiplyObligationFixedRate.tag: {
            if ((0, kit_1.isNone)(reserveAddress1)) {
                throw new Error('MultiplyObligationFixedRate PDA requires reserve address 1 (collateral)');
            }
            if ((0, kit_1.isNone)(reserveAddress2)) {
                throw new Error('MultiplyObligationFixedRate PDA requires reserve address 2 (debt)');
            }
            return new MultiplyObligationFixedRate(reserveAddress1.value, reserveAddress2.value, kaminoMarket.programId);
        }
        case LeverageObligationFixedRate.tag: {
            if ((0, kit_1.isNone)(reserveAddress1)) {
                throw new Error('LeverageObligationFixedRate PDA requires reserve address 1 (collateral)');
            }
            if ((0, kit_1.isNone)(reserveAddress2)) {
                throw new Error('LeverageObligationFixedRate PDA requires reserve address 2 (debt)');
            }
            return new LeverageObligationFixedRate(reserveAddress1.value, reserveAddress2.value, kaminoMarket.programId);
        }
        default: {
            throw new Error('Invalid obligation type');
        }
    }
}
function getObligationTypeFromObligation(kaminoMarket, obligation) {
    switch (obligation.obligationTag) {
        case VanillaObligation.tag: {
            return new VanillaObligation(kaminoMarket.programId);
        }
        case MultiplyObligation.tag: {
            return new MultiplyObligation(obligation.getDeposits()[0].mintAddress, obligation.getBorrows()[0].mintAddress, kaminoMarket.programId);
        }
        case LeverageObligation.tag: {
            return new LeverageObligation(obligation.getDeposits()[0].mintAddress, obligation.getBorrows()[0].mintAddress, kaminoMarket.programId);
        }
        case LendingObligation.tag: {
            return new LendingObligation(obligation.getDeposits()[0].mintAddress, kaminoMarket.programId);
        }
        case LendingObligationFixedRate.tag: {
            return new LendingObligationFixedRate(obligation.getDeposits()[0].reserveAddress, kaminoMarket.programId);
        }
        case MultiplyObligationFixedRate.tag: {
            return new MultiplyObligationFixedRate(obligation.getDeposits()[0].reserveAddress, obligation.getBorrows()[0].reserveAddress, kaminoMarket.programId);
        }
        case LeverageObligationFixedRate.tag: {
            return new LeverageObligationFixedRate(obligation.getDeposits()[0].reserveAddress, obligation.getBorrows()[0].reserveAddress, kaminoMarket.programId);
        }
        default: {
            throw new Error('Invalid obligation type');
        }
    }
}
//# sourceMappingURL=ObligationType.js.map