Skip to main content

klend_interface/helpers/
context.rs

1use solana_instruction::Instruction;
2use solana_pubkey::Pubkey;
3
4use super::info::{ObligationContext, ObligationContextError};
5
6impl ObligationContext {
7    /// Borrow liquidity from a reserve against this obligation.
8    pub fn borrow(
9        &self,
10        owner: Pubkey,
11        borrow_reserve: &Pubkey,
12        user_destination_liquidity: Pubkey,
13        amount: u64,
14    ) -> Result<Vec<Instruction>, ObligationContextError> {
15        let r = self
16            .find_reserve(borrow_reserve)
17            .ok_or(ObligationContextError::ReserveNotFound(*borrow_reserve))?;
18        let farms = self.debt_farms(borrow_reserve);
19        Ok(super::borrow::borrow(
20            owner,
21            &r.info,
22            &self.obligation,
23            &self.all_reserve_infos(),
24            user_destination_liquidity,
25            amount,
26            farms.as_ref(),
27        ))
28    }
29
30    /// Deposit liquidity into a reserve and credit collateral to this obligation.
31    pub fn deposit(
32        &self,
33        owner: Pubkey,
34        reserve: &Pubkey,
35        user_source_liquidity: Pubkey,
36        amount: u64,
37    ) -> Result<Vec<Instruction>, ObligationContextError> {
38        let r = self
39            .find_reserve(reserve)
40            .ok_or(ObligationContextError::ReserveNotFound(*reserve))?;
41        let farms = self.collateral_farms(reserve);
42        Ok(super::deposit::deposit_to_obligation(
43            owner,
44            &r.info,
45            &self.obligation,
46            &self.all_reserve_infos(),
47            user_source_liquidity,
48            amount,
49            farms.as_ref(),
50        ))
51    }
52
53    /// Withdraw collateral from this obligation and redeem it for liquidity.
54    pub fn withdraw(
55        &self,
56        owner: Pubkey,
57        reserve: &Pubkey,
58        user_destination_liquidity: Pubkey,
59        collateral_amount: u64,
60    ) -> Result<Vec<Instruction>, ObligationContextError> {
61        let r = self
62            .find_reserve(reserve)
63            .ok_or(ObligationContextError::ReserveNotFound(*reserve))?;
64        let farms = self.collateral_farms(reserve);
65        Ok(super::withdraw::withdraw(
66            owner,
67            &r.info,
68            &self.obligation,
69            &self.all_reserve_infos(),
70            user_destination_liquidity,
71            collateral_amount,
72            farms.as_ref(),
73        ))
74    }
75
76    /// Withdraw collateral (cTokens) from this obligation without redeeming.
77    pub fn withdraw_collateral(
78        &self,
79        owner: Pubkey,
80        reserve: &Pubkey,
81        user_destination_collateral: Pubkey,
82        collateral_amount: u64,
83    ) -> Result<Vec<Instruction>, ObligationContextError> {
84        let r = self
85            .find_reserve(reserve)
86            .ok_or(ObligationContextError::ReserveNotFound(*reserve))?;
87        let farms = self.collateral_farms(reserve);
88        Ok(super::withdraw::withdraw_collateral(
89            owner,
90            &r.info,
91            &self.obligation,
92            &self.all_reserve_infos(),
93            user_destination_collateral,
94            collateral_amount,
95            farms.as_ref(),
96        ))
97    }
98
99    /// Repay borrowed liquidity.
100    pub fn repay(
101        &self,
102        owner: Pubkey,
103        reserve: &Pubkey,
104        user_source_liquidity: Pubkey,
105        amount: u64,
106    ) -> Result<Vec<Instruction>, ObligationContextError> {
107        let r = self
108            .find_reserve(reserve)
109            .ok_or(ObligationContextError::ReserveNotFound(*reserve))?;
110        let farms = self.debt_farms(reserve);
111        Ok(super::repay::repay(
112            owner,
113            &r.info,
114            &self.obligation,
115            &self.all_reserve_infos(),
116            user_source_liquidity,
117            amount,
118            farms.as_ref(),
119        ))
120    }
121
122    /// Atomically repay a borrow, withdraw collateral, and redeem it for liquidity.
123    #[allow(clippy::too_many_arguments)]
124    pub fn repay_and_withdraw(
125        &self,
126        owner: Pubkey,
127        repay_reserve: &Pubkey,
128        withdraw_reserve: &Pubkey,
129        user_source_liquidity: Pubkey,
130        user_destination_liquidity: Pubkey,
131        repay_amount: u64,
132        withdraw_collateral_amount: u64,
133    ) -> Result<Vec<Instruction>, ObligationContextError> {
134        let rr = self
135            .find_reserve(repay_reserve)
136            .ok_or(ObligationContextError::ReserveNotFound(*repay_reserve))?;
137        let wr = self
138            .find_reserve(withdraw_reserve)
139            .ok_or(ObligationContextError::ReserveNotFound(*withdraw_reserve))?;
140        let collateral_farms = self.collateral_farms(withdraw_reserve);
141        let debt_farms = self.debt_farms(repay_reserve);
142        Ok(super::repay::repay_and_withdraw(
143            owner,
144            &rr.info,
145            &wr.info,
146            &self.obligation,
147            &self.all_reserve_infos(),
148            user_source_liquidity,
149            user_destination_liquidity,
150            repay_amount,
151            withdraw_collateral_amount,
152            collateral_farms.as_ref(),
153            debt_farms.as_ref(),
154        ))
155    }
156
157    /// Atomically deposit to one reserve and withdraw from another (rebalancing).
158    #[allow(clippy::too_many_arguments)]
159    pub fn deposit_and_withdraw(
160        &self,
161        owner: Pubkey,
162        deposit_reserve: &Pubkey,
163        withdraw_reserve: &Pubkey,
164        user_source_liquidity: Pubkey,
165        user_destination_liquidity: Pubkey,
166        deposit_amount: u64,
167        withdraw_collateral_amount: u64,
168    ) -> Result<Vec<Instruction>, ObligationContextError> {
169        let dr = self
170            .find_reserve(deposit_reserve)
171            .ok_or(ObligationContextError::ReserveNotFound(*deposit_reserve))?;
172        let wr = self
173            .find_reserve(withdraw_reserve)
174            .ok_or(ObligationContextError::ReserveNotFound(*withdraw_reserve))?;
175        let deposit_farms = self.collateral_farms(deposit_reserve);
176        let withdraw_farms = self.collateral_farms(withdraw_reserve);
177        Ok(super::compound::deposit_and_withdraw(
178            owner,
179            &dr.info,
180            &wr.info,
181            &self.obligation,
182            &self.all_reserve_infos(),
183            user_source_liquidity,
184            user_destination_liquidity,
185            deposit_amount,
186            withdraw_collateral_amount,
187            deposit_farms.as_ref(),
188            withdraw_farms.as_ref(),
189        ))
190    }
191
192    /// Liquidate an undercollateralized obligation.
193    #[allow(clippy::too_many_arguments)]
194    pub fn liquidate(
195        &self,
196        liquidator: Pubkey,
197        repay_reserve: &Pubkey,
198        withdraw_reserve: &Pubkey,
199        user_source_liquidity: Pubkey,
200        user_destination_collateral: Pubkey,
201        user_destination_liquidity: Pubkey,
202        amount: u64,
203        min_received: u64,
204        max_ltv_override: u64,
205    ) -> Result<Vec<Instruction>, ObligationContextError> {
206        let rr = self
207            .find_reserve(repay_reserve)
208            .ok_or(ObligationContextError::ReserveNotFound(*repay_reserve))?;
209        let wr = self
210            .find_reserve(withdraw_reserve)
211            .ok_or(ObligationContextError::ReserveNotFound(*withdraw_reserve))?;
212        let collateral_farms = self.collateral_farms(withdraw_reserve);
213        let debt_farms = self.debt_farms(repay_reserve);
214        Ok(super::liquidate::liquidate(
215            liquidator,
216            &rr.info,
217            &wr.info,
218            &self.obligation,
219            &self.all_reserve_infos(),
220            user_source_liquidity,
221            user_destination_collateral,
222            user_destination_liquidity,
223            amount,
224            min_received,
225            max_ltv_override,
226            collateral_farms.as_ref(),
227            debt_farms.as_ref(),
228        ))
229    }
230
231    /// Request an elevation group change for this obligation.
232    pub fn request_elevation_group(&self, owner: Pubkey, elevation_group: u8) -> Vec<Instruction> {
233        super::obligation::request_elevation_group(
234            owner,
235            self.lending_market,
236            &self.obligation,
237            &self.all_reserve_infos(),
238            elevation_group,
239        )
240    }
241}