use solana_instruction::Instruction;
use solana_pubkey::Pubkey;
use super::{
common::{
build_refresh_all_obligation_reserves, build_refresh_obligation, build_refresh_reserve,
},
info::{FarmsAccounts, ObligationInfo, ReserveInfo},
};
use crate::{
instructions::withdraw::{
redeem_reserve_collateral, withdraw_obligation_collateral_and_redeem_reserve_collateral_v2,
withdraw_obligation_collateral_v2, RedeemReserveCollateralAccounts,
WithdrawObligationCollateralAndRedeemReserveCollateralV2Accounts,
WithdrawObligationCollateralV2Accounts,
},
pda::{self, ReservePdas},
KLEND_PROGRAM_ID,
};
pub fn withdraw(
owner: Pubkey,
withdraw_reserve: &ReserveInfo,
obligation: &ObligationInfo,
obligation_reserves: &[ReserveInfo],
user_destination_liquidity: Pubkey,
collateral_amount: u64,
farms: Option<&FarmsAccounts>,
) -> Vec<Instruction> {
let pdas = ReservePdas::derive(&KLEND_PROGRAM_ID, &withdraw_reserve.address);
let (lma, _) =
pda::lending_market_authority(&KLEND_PROGRAM_ID, &withdraw_reserve.lending_market);
let mut ixs = build_refresh_all_obligation_reserves(
obligation,
obligation_reserves,
&[withdraw_reserve.address],
);
ixs.push(build_refresh_reserve(withdraw_reserve));
ixs.push(build_refresh_obligation(
&withdraw_reserve.lending_market,
obligation,
));
ixs.push(
withdraw_obligation_collateral_and_redeem_reserve_collateral_v2(
WithdrawObligationCollateralAndRedeemReserveCollateralV2Accounts {
owner,
obligation: obligation.address,
lending_market: withdraw_reserve.lending_market,
lending_market_authority: lma,
withdraw_reserve: withdraw_reserve.address,
reserve_liquidity_mint: withdraw_reserve.liquidity_mint,
reserve_source_collateral: pdas.collateral_supply_vault,
reserve_collateral_mint: pdas.collateral_mint,
reserve_liquidity_supply: pdas.liquidity_supply_vault,
user_destination_liquidity,
placeholder_user_destination_collateral: None,
liquidity_token_program: withdraw_reserve.liquidity_token_program,
obligation_farm_user_state: farms.map(|f| f.obligation_farm_user_state),
reserve_farm_state: farms.map(|f| f.reserve_farm_state),
},
collateral_amount,
),
);
ixs
}
pub fn withdraw_collateral(
owner: Pubkey,
withdraw_reserve: &ReserveInfo,
obligation: &ObligationInfo,
obligation_reserves: &[ReserveInfo],
user_destination_collateral: Pubkey,
collateral_amount: u64,
farms: Option<&FarmsAccounts>,
) -> Vec<Instruction> {
let pdas = ReservePdas::derive(&KLEND_PROGRAM_ID, &withdraw_reserve.address);
let (lma, _) =
pda::lending_market_authority(&KLEND_PROGRAM_ID, &withdraw_reserve.lending_market);
let mut ixs = build_refresh_all_obligation_reserves(
obligation,
obligation_reserves,
&[withdraw_reserve.address],
);
ixs.push(build_refresh_reserve(withdraw_reserve));
ixs.push(build_refresh_obligation(
&withdraw_reserve.lending_market,
obligation,
));
ixs.push(withdraw_obligation_collateral_v2(
WithdrawObligationCollateralV2Accounts {
owner,
obligation: obligation.address,
lending_market: withdraw_reserve.lending_market,
lending_market_authority: lma,
withdraw_reserve: withdraw_reserve.address,
reserve_source_collateral: pdas.collateral_supply_vault,
user_destination_collateral,
obligation_farm_user_state: farms.map(|f| f.obligation_farm_user_state),
reserve_farm_state: farms.map(|f| f.reserve_farm_state),
},
collateral_amount,
));
ixs
}
pub fn redeem(
owner: Pubkey,
reserve: &ReserveInfo,
user_source_collateral: Pubkey,
user_destination_liquidity: Pubkey,
collateral_amount: u64,
) -> Vec<Instruction> {
let pdas = ReservePdas::derive(&KLEND_PROGRAM_ID, &reserve.address);
let (lma, _) = pda::lending_market_authority(&KLEND_PROGRAM_ID, &reserve.lending_market);
vec![
build_refresh_reserve(reserve),
redeem_reserve_collateral(
RedeemReserveCollateralAccounts {
owner,
lending_market: reserve.lending_market,
reserve: reserve.address,
lending_market_authority: lma,
reserve_liquidity_mint: reserve.liquidity_mint,
reserve_collateral_mint: pdas.collateral_mint,
reserve_liquidity_supply: pdas.liquidity_supply_vault,
user_source_collateral,
user_destination_liquidity,
liquidity_token_program: reserve.liquidity_token_program,
},
collateral_amount,
),
]
}