apricot_client/
instructions.rs

1use solana_program::{
2    instruction::{AccountMeta, Instruction},
3    pubkey::Pubkey,
4    system_program,
5};
6use spl_token;
7
8use crate::consts;
9
10#[repr(packed)]
11pub struct UpdateUserAssetConfigParam {
12    pub use_as_collateral: u8,
13    pub pool_id: u8,
14}
15
16#[repr(packed)]
17pub struct AddUserAndDepositParam {
18    pub page_id: u16,
19    pub amount: u64,
20    pub pool_id: u8,
21}
22
23#[repr(packed)]
24pub struct DepositParam {
25    pub amount: u64,
26    pub pool_id: u8,
27}
28
29#[repr(packed)]
30pub struct WithdrawParam {
31    pub withdraw_all: u8,
32    pub amount: u64,
33    pub pool_id: u8,
34}
35
36#[repr(packed)]
37pub struct BorrowParam {
38    pub amount: u64,
39    pub pool_id: u8,
40}
41
42#[repr(packed)]
43pub struct RepayParam {
44    pub repay_all: u8,
45    pub amount: u64,
46    pub pool_id: u8,
47}
48
49#[repr(packed)]
50pub struct ExternLiquidateParam {
51    // how much collateral liquidator wants to receive
52    pub min_collateral_amount: u64,
53    // how much debt liquidator wants to help repay
54    pub repaid_borrow_amount: u64,
55    pub collateral_pool_id: u8,
56    pub borrowed_pool_id: u8,
57}
58
59#[inline(always)]
60pub fn mut_cast<T>(data: &mut [u8]) -> &mut T {
61    assert!(data.len() >= std::mem::size_of::<T>());
62    return unsafe { std::mem::transmute(data.as_ptr()) };
63}
64
65pub fn deposit(
66    user_wallet: &Pubkey, // user wallet account, needs to be signer
67    user_spl: &Pubkey,    // user's SPL token account
68    amount: u64,
69    pool_id: u8,
70) -> Instruction {
71    deposit_full(
72        user_wallet,
73        user_spl,
74        &consts::get_user_info_k(user_wallet),
75        &consts::get_asset_pool_k(pool_id),
76        &consts::get_asset_pool_spl_k(&spl_token::ID, pool_id),
77        &consts::get_pool_summaries_k(),
78        &consts::get_price_summaries_k(),
79        &spl_token::ID,
80        &consts::program::ID,
81        amount,
82        pool_id,
83    )
84}
85
86pub fn deposit_full(
87    user_wallet: &Pubkey,     // user wallet account, needs to be signer
88    user_spl: &Pubkey,        // user's SPL token account
89    user_info: &Pubkey,       // consts::get_user_info_k(user_wallet_key)
90    asset_pool: &Pubkey,      // consts::get_asset_pool_k(pool_id)
91    asset_pool_spl: &Pubkey,  // consts::get_asset_pool_spl_k(token_program, pool_id)
92    pool_summaries: &Pubkey,  // consts::get_pool_summaries_k()
93    price_summaries: &Pubkey, // consts::get_pool_summaries_k()
94    token_program: &Pubkey,
95    program_id: &Pubkey, // consts::program::ID
96
97    amount: u64,
98    pool_id: u8,
99) -> Instruction {
100    let data_size = 1 + std::mem::size_of::<DepositParam>();
101    let mut buffer = vec![0; data_size];
102
103    buffer[0] = consts::CMD_DEPOSIT;
104    let mut param = mut_cast::<DepositParam>(&mut buffer[1..]);
105    param.amount = amount;
106    param.pool_id = pool_id;
107
108    Instruction {
109        program_id: *program_id,
110        accounts: vec![
111            AccountMeta::new_readonly(*user_wallet, true),
112            AccountMeta::new(*user_spl, false),
113            AccountMeta::new(*user_info, false),
114            AccountMeta::new(*asset_pool, false),
115            AccountMeta::new(*asset_pool_spl, false),
116            AccountMeta::new(*pool_summaries, false),
117            AccountMeta::new(*price_summaries, false),
118            AccountMeta::new_readonly(*token_program, false),
119        ],
120        data: buffer,
121    }
122}
123
124pub fn add_user_and_deposit(
125    user_wallet: &Pubkey, // user wallet account, needs to be signer
126    user_spl: &Pubkey,    // user's SPL token account
127    amount: u64,
128    pool_id: u8,
129    page_id: u16,
130) -> Instruction {
131    add_user_and_deposit_full(
132        user_wallet,
133        user_spl,
134        &consts::get_user_pages_stats_k(),
135        &consts::get_users_page_k(page_id),
136        &consts::get_user_info_k(user_wallet),
137        &consts::get_asset_pool_k(pool_id),
138        &consts::get_asset_pool_spl_k(&spl_token::ID, pool_id),
139        &consts::get_pool_summaries_k(),
140        &consts::get_price_summaries_k(),
141        &system_program::ID,
142        &spl_token::ID,
143        &consts::program::ID,
144        amount,
145        pool_id,
146        page_id,
147    )
148}
149
150pub fn add_user_and_deposit_full(
151    user_wallet: &Pubkey,      // user wallet account, needs to be signer
152    user_spl: &Pubkey,         // user's SPL token account
153    user_pages_stats: &Pubkey, // consts::get_user_pages_stats_k()
154    users_page: &Pubkey,       // consts::get_users_page_k(page_id)
155    user_info: &Pubkey,        // consts::get_user_info_k(user_wallet_key)
156    asset_pool: &Pubkey,       // consts::get_asset_pool_k(pool_id)
157    asset_pool_spl: &Pubkey,   // consts::get_asset_pool_spl_k(token_program, pool_id)
158    pool_summaries: &Pubkey,   // consts::get_pool_summaries_k()
159    price_summaries: &Pubkey,  // consts::get_pool_summaries_k()
160    system_program: &Pubkey,
161    token_program: &Pubkey,
162    program_id: &Pubkey, // consts::program::ID
163
164    amount: u64,
165    pool_id: u8,
166    page_id: u16,
167) -> Instruction {
168    let data_size = 1 + std::mem::size_of::<AddUserAndDepositParam>();
169    let mut buffer = vec![0; data_size];
170
171    buffer[0] = consts::CMD_ADD_USER_AND_DEPOSIT;
172    let mut param = mut_cast::<AddUserAndDepositParam>(&mut buffer[1..]);
173    param.amount = amount;
174    param.pool_id = pool_id;
175    param.page_id = page_id;
176
177    Instruction {
178        program_id: *program_id,
179        accounts: vec![
180            AccountMeta::new(*user_wallet, true),
181            AccountMeta::new(*user_spl, false),
182            AccountMeta::new(*user_pages_stats, false),
183            AccountMeta::new(*users_page, false),
184            AccountMeta::new(*user_info, false),
185            AccountMeta::new(*asset_pool, false),
186            AccountMeta::new(*asset_pool_spl, false),
187            AccountMeta::new(*pool_summaries, false),
188            AccountMeta::new(*price_summaries, false),
189            AccountMeta::new_readonly(*system_program, false),
190            AccountMeta::new_readonly(*token_program, false),
191        ],
192        data: buffer,
193    }
194}
195
196pub fn withdraw(
197    user_wallet: &Pubkey, // user wallet account, needs to be signer
198    user_spl: &Pubkey,    // user's SPL token account
199    withdraw_all: bool,
200    amount: u64,
201    pool_id: u8,
202    page_id: u16,
203) -> Instruction {
204    withdraw_full(
205        user_wallet,
206        user_spl,
207        &consts::get_user_info_k(user_wallet),
208        &consts::get_asset_pool_k(pool_id),
209        &consts::get_asset_pool_spl_k(&spl_token::ID, pool_id),
210        &consts::get_pool_summaries_k(),
211        &consts::get_price_summaries_k(),
212        &consts::get_base_pda(),
213        &spl_token::ID,
214        &consts::program::ID,
215        withdraw_all,
216        amount,
217        pool_id,
218        page_id,
219    )
220}
221
222pub fn withdraw_full(
223    user_wallet: &Pubkey,     // user wallet account, needs to be signer
224    user_spl: &Pubkey,        // user's SPL token account
225    user_info: &Pubkey,       // consts::get_user_info_k(user_wallet_key)
226    asset_pool: &Pubkey,      // consts::get_asset_pool_k(pool_id)
227    asset_pool_spl: &Pubkey,  // consts::get_asset_pool_spl_k(token_program, pool_id)
228    pool_summaries: &Pubkey,  // consts::get_pool_summaries_k()
229    price_summaries: &Pubkey, // consts::get_price_summaries_k()
230    base_pda: &Pubkey,        // consts::get_base_pda()
231    token_program: &Pubkey,
232    program_id: &Pubkey, // consts::program::ID
233
234    withdraw_all: bool,
235    amount: u64,
236    pool_id: u8,
237    page_id: u16,
238) -> Instruction {
239    let data_size = 1 + std::mem::size_of::<WithdrawParam>();
240    let mut buffer = vec![0; data_size];
241
242    buffer[0] = if withdraw_all {
243        consts::CMD_WITHDRAW_AND_REMOVE_USER
244    } else {
245        consts::CMD_WITHDRAW
246    };
247    let mut param = mut_cast::<WithdrawParam>(&mut buffer[1..]);
248    param.withdraw_all = if withdraw_all { 1 } else { 0 };
249    param.amount = amount;
250    param.pool_id = pool_id;
251
252    let mut accounts = vec![
253        AccountMeta::new_readonly(*user_wallet, true),
254        AccountMeta::new(*user_spl, false),
255    ];
256    if withdraw_all {
257        accounts.push(AccountMeta::new(consts::get_user_pages_stats_k(), false));
258        accounts.push(AccountMeta::new(consts::get_users_page_k(page_id), false));
259    }
260    accounts.push(AccountMeta::new(*user_info, false));
261    accounts.push(AccountMeta::new(*asset_pool, false));
262    accounts.push(AccountMeta::new(*asset_pool_spl, false));
263    accounts.push(AccountMeta::new(*pool_summaries, false));
264    accounts.push(AccountMeta::new_readonly(*price_summaries, false));
265    accounts.push(AccountMeta::new_readonly(*base_pda, false));
266    accounts.push(AccountMeta::new_readonly(*token_program, false));
267    Instruction {
268        program_id: *program_id,
269        accounts: accounts,
270        data: buffer,
271    }
272}
273
274pub fn borrow(
275    user_wallet: &Pubkey, // user wallet account, needs to be signer
276    user_spl: &Pubkey,    // user's SPL token account
277    amount: u64,
278    pool_id: u8,
279) -> Instruction {
280    borrow_full(
281        user_wallet,
282        user_spl,
283        &consts::get_user_info_k(user_wallet),
284        &consts::get_asset_pool_k(pool_id),
285        &consts::get_asset_pool_spl_k(&spl_token::ID, pool_id),
286        &consts::get_pool_summaries_k(),
287        &consts::get_price_summaries_k(),
288        &consts::get_base_pda(),
289        &spl_token::ID,
290        &consts::program::ID,
291        amount,
292        pool_id,
293    )
294}
295
296pub fn borrow_full(
297    user_wallet: &Pubkey,     // user wallet account, needs to be signer
298    user_spl: &Pubkey,        // user's SPL token account
299    user_info: &Pubkey,       // consts::get_user_info_k(user_wallet_key)
300    asset_pool: &Pubkey,      // consts::get_asset_pool_k(pool_id)
301    asset_pool_spl: &Pubkey,  // consts::get_asset_pool_spl_k(token_program, pool_id)
302    pool_summaries: &Pubkey,  // consts::get_pool_summaries_k()
303    price_summaries: &Pubkey, // consts::get_price_summaries_k()
304    base_pda: &Pubkey,        // consts::get_base_pda()
305    token_program: &Pubkey,
306    program_id: &Pubkey, // consts::program::ID
307
308    amount: u64,
309    pool_id: u8,
310) -> Instruction {
311    let data_size = 1 + std::mem::size_of::<BorrowParam>();
312    let mut buffer = vec![0; data_size];
313
314    buffer[0] = consts::CMD_BORROW;
315    let mut param = mut_cast::<BorrowParam>(&mut buffer[1..]);
316    param.amount = amount;
317    param.pool_id = pool_id;
318
319    Instruction {
320        program_id: *program_id,
321        accounts: vec![
322            AccountMeta::new_readonly(*user_wallet, true),
323            AccountMeta::new(*user_spl, false),
324            AccountMeta::new(*user_info, false),
325            AccountMeta::new(*asset_pool, false),
326            AccountMeta::new(*asset_pool_spl, false),
327            AccountMeta::new(*pool_summaries, false),
328            AccountMeta::new_readonly(*price_summaries, false),
329            AccountMeta::new_readonly(*base_pda, false),
330            AccountMeta::new_readonly(*token_program, false),
331        ],
332        data: buffer,
333    }
334}
335
336pub fn repay(
337    user_wallet: &Pubkey, // user wallet account, needs to be signer
338    user_spl: &Pubkey,    // user's SPL token account
339    repay_all: bool,
340    amount: u64,
341    pool_id: u8,
342) -> Instruction {
343    repay_full(
344        user_wallet,
345        user_spl,
346        &consts::get_user_info_k(user_wallet),
347        &consts::get_asset_pool_k(pool_id),
348        &consts::get_asset_pool_spl_k(&spl_token::ID, pool_id),
349        &consts::get_pool_summaries_k(),
350        &spl_token::ID,
351        &consts::program::ID,
352        repay_all,
353        amount,
354        pool_id,
355    )
356}
357
358pub fn repay_full(
359    user_wallet: &Pubkey,    // user wallet account, needs to be signer
360    user_spl: &Pubkey,       // user's SPL token account
361    user_info: &Pubkey,      // consts::get_user_info_k(user_wallet_key)
362    asset_pool: &Pubkey,     // consts::get_asset_pool_k(pool_id)
363    asset_pool_spl: &Pubkey, // consts::get_asset_pool_spl_k(token_program, pool_id)
364    pool_summaries: &Pubkey, // consts::get_pool_summaries_k()
365    token_program: &Pubkey,
366    program_id: &Pubkey, // consts::program::ID
367
368    repay_all: bool,
369    amount: u64,
370    pool_id: u8,
371) -> Instruction {
372    let data_size = 1 + std::mem::size_of::<RepayParam>();
373    let mut buffer = vec![0; data_size];
374
375    buffer[0] = consts::CMD_REPAY;
376    let mut param = mut_cast::<RepayParam>(&mut buffer[1..]);
377    param.repay_all = if repay_all { 1 } else { 0 };
378    param.amount = amount;
379    param.pool_id = pool_id;
380
381    Instruction {
382        program_id: *program_id,
383        accounts: vec![
384            AccountMeta::new_readonly(*user_wallet, true),
385            AccountMeta::new(*user_spl, false),
386            AccountMeta::new(*user_info, false),
387            AccountMeta::new(*asset_pool, false),
388            AccountMeta::new(*asset_pool_spl, false),
389            AccountMeta::new(*pool_summaries, false),
390            AccountMeta::new_readonly(*token_program, false),
391        ],
392        data: buffer,
393    }
394}
395
396pub fn refresh_user(user_wallet: &Pubkey, // user wallet account
397) -> Instruction {
398    let data_size = 1 + 0; // no param
399    let mut buffer = vec![0; data_size];
400
401    let program_id = consts::program::ID;
402    let user_info = consts::get_user_info_k(user_wallet);
403    let pool_summaries = consts::get_pool_summaries_k();
404
405    buffer[0] = consts::CMD_REFRESH_USER;
406
407    Instruction {
408        program_id: program_id,
409        accounts: vec![
410            AccountMeta::new_readonly(*user_wallet, false),
411            AccountMeta::new(user_info, false),
412            AccountMeta::new_readonly(pool_summaries, false),
413        ],
414        data: buffer,
415    }
416}
417
418pub fn extern_liquidate(
419    liquidated_wallet: &Pubkey, // wallet key for account to be liquidated
420    liquidator_wallet: &Pubkey, // wallet key for liquidator, signer
421    liquidator_collateral_spl: &Pubkey, // liquidator's SPL token account for collateral asset
422    liquidator_borrowed_spl: &Pubkey, // liquidator's SPL token account for repaid asset
423    repaid_borrow_amount: u64,
424    min_collateral_amount: u64,
425    borrowed_pool_id: u8,
426    collateral_pool_id: u8,
427) -> Instruction {
428    extern_liquidate_full(
429        liquidated_wallet,
430        liquidator_wallet,
431        &consts::get_user_info_k(liquidated_wallet),
432        &consts::get_base_pda(),
433        liquidator_collateral_spl,
434        liquidator_borrowed_spl,
435        &consts::get_asset_pool_k(collateral_pool_id),
436        &consts::get_asset_pool_spl_k(&spl_token::ID, collateral_pool_id),
437        &consts::get_asset_pool_k(borrowed_pool_id),
438        &consts::get_asset_pool_spl_k(&spl_token::ID, borrowed_pool_id),
439        &consts::get_pool_summaries_k(),
440        &spl_token::ID,
441        &consts::program::ID,
442        repaid_borrow_amount,
443        min_collateral_amount,
444        borrowed_pool_id,
445        collateral_pool_id,
446    )
447}
448
449// liquidator will help repay "borrowed" and in exchange receive "collateral" asset at 1% discount
450pub fn extern_liquidate_full(
451    liquidated_wallet: &Pubkey, // wallet key for account to be liquidated
452    liquidator_wallet: &Pubkey, // wallet key for liquidator, signer
453
454    user_info: &Pubkey, // consts::get_user_info_k(liquidated_wallet)
455    base_pda: &Pubkey,  // consts::get_base_pda()
456
457    liquidator_collateral_spl: &Pubkey, // liquidator's SPL token account for collateral asset
458    liquidator_borrowed_spl: &Pubkey,   // liquidator's SPL token account for repaid asset
459
460    collateral_asset_pool: &Pubkey, // consts::get_asset_pool_k(collateral_pool_id)
461    collateral_asset_pool_spl: &Pubkey, // consts::get_asset_pool_spl_k(token_program, collateral_pool_id)
462
463    borrowed_asset_pool: &Pubkey, // consts::get_asset_pool_k(borrowed_pool_id)
464    borrowed_asset_pool_spl: &Pubkey, // consts::get_asset_pool_spl_k(token_program, borrowed_pool_id)
465
466    pool_summaries: &Pubkey, // consts::get_pool_summaries_k()
467    token_program: &Pubkey,
468    program_id: &Pubkey, // consts::program::ID
469
470    repaid_borrow_amount: u64,
471    min_collateral_amount: u64,
472    borrowed_pool_id: u8,
473    collateral_pool_id: u8,
474) -> Instruction {
475    let data_size = 1 + std::mem::size_of::<ExternLiquidateParam>();
476    let mut buffer = vec![0; data_size];
477    buffer[0] = consts::CMD_EXTERN_LIQUIDATE;
478
479    let mut param = mut_cast::<ExternLiquidateParam>(&mut buffer[1..]);
480    param.repaid_borrow_amount = repaid_borrow_amount;
481    param.min_collateral_amount = min_collateral_amount;
482    param.borrowed_pool_id = borrowed_pool_id;
483    param.collateral_pool_id = collateral_pool_id;
484
485    Instruction {
486        program_id: *program_id,
487        accounts: vec![
488            AccountMeta::new_readonly(*liquidated_wallet, false),
489            AccountMeta::new_readonly(*liquidator_wallet, true),
490            AccountMeta::new(*user_info, false),
491            AccountMeta::new_readonly(*base_pda, false),
492            AccountMeta::new(*liquidator_collateral_spl, false),
493            AccountMeta::new(*liquidator_borrowed_spl, false),
494            AccountMeta::new(*collateral_asset_pool, false),
495            AccountMeta::new(*collateral_asset_pool_spl, false),
496            AccountMeta::new(*borrowed_asset_pool, false),
497            AccountMeta::new(*borrowed_asset_pool_spl, false),
498            AccountMeta::new(*pool_summaries, false),
499            AccountMeta::new_readonly(*token_program, false),
500        ],
501        data: buffer,
502    }
503}
504
505// APT Reward has one week accumalating period and one week vestin period,
506// Use this method to make any APT reward post-vesting available, contract will find how much APT
507// reward has finished vesting and make it available.
508pub fn make_lm_reward_claimable(user_wallet: &Pubkey) -> Instruction {
509    let user_info = consts::get_user_info_k(user_wallet);
510    let pool_summaries = consts::get_pool_summaries_k();
511
512    let mut buffer = vec![0; 1];
513    buffer[0] = consts::CMD_MAKE_LM_REWARD_AVAILABLE;
514
515    Instruction {
516        program_id: consts::program::ID,
517        accounts: vec![
518            AccountMeta::new_readonly(*user_wallet, true),
519            AccountMeta::new_readonly(*user_wallet, false),
520            AccountMeta::new(user_info, false),
521            AccountMeta::new(pool_summaries, false),
522        ],
523        data: buffer,
524    }
525}
526
527pub fn claim_apt_lm_reward(user_wallet: &Pubkey, user_apt_spl: &Pubkey) -> Instruction {
528    let base_pda = consts::get_base_pda();
529    let user_info = consts::get_user_info_k(user_wallet);
530    let lm_apt_vault = consts::lm_apt_vault::ID;
531    let pool_summaries = consts::get_pool_summaries_k();
532    let price_summaries = consts::get_price_summaries_k();
533
534    let mut buffer = vec![0; 1];
535    buffer[0] = consts::CMD_CLAIM_APT_LM_REWARD;
536    Instruction {
537        program_id: consts::program::ID,
538        accounts: vec![
539            AccountMeta::new_readonly(base_pda, false),
540            AccountMeta::new_readonly(*user_wallet, true),
541            AccountMeta::new(user_info, false),
542            AccountMeta::new(*user_apt_spl, false),
543            AccountMeta::new(lm_apt_vault, false),
544            AccountMeta::new(pool_summaries, false),
545            AccountMeta::new_readonly(price_summaries, false),
546            AccountMeta::new_readonly(spl_token::ID, false),
547        ],
548        data: buffer,
549    }
550}