Skip to main content

kvault_interface/instructions/
deposit.rs

1use borsh::BorshSerialize;
2use solana_instruction::{AccountMeta, Instruction};
3use solana_pubkey::Pubkey;
4
5use crate::{discriminators, pda, util::*, KVAULT_PROGRAM_ID};
6
7// ---------------------------------------------------------------------------
8// Accounts shared by deposit and buy
9// ---------------------------------------------------------------------------
10
11/// Account addresses required by the `deposit` and `buy` instructions.
12pub struct DepositAccounts {
13    pub user: Pubkey,
14    pub vault_state: Pubkey,
15    pub token_vault: Pubkey,
16    pub token_mint: Pubkey,
17    pub base_vault_authority: Pubkey,
18    pub shares_mint: Pubkey,
19    pub user_token_ata: Pubkey,
20    pub user_shares_ata: Pubkey,
21    pub klend_program: Pubkey,
22    pub token_program: Pubkey,
23    pub shares_token_program: Pubkey,
24}
25
26fn build_deposit_accounts(accounts: &DepositAccounts) -> Vec<AccountMeta> {
27    let (evt_auth, _) = pda::event_authority(&KVAULT_PROGRAM_ID);
28    vec![
29        signer_writable(accounts.user),
30        writable(accounts.vault_state),
31        writable(accounts.token_vault),
32        readonly(accounts.token_mint),
33        readonly(accounts.base_vault_authority),
34        writable(accounts.shares_mint),
35        writable(accounts.user_token_ata),
36        writable(accounts.user_shares_ata),
37        readonly(accounts.klend_program),
38        readonly(accounts.token_program),
39        readonly(accounts.shares_token_program),
40        // event_cpi accounts
41        readonly(evt_auth),
42        readonly(KVAULT_PROGRAM_ID),
43    ]
44}
45
46// ---------------------------------------------------------------------------
47// deposit
48// ---------------------------------------------------------------------------
49
50/// Build a raw `deposit` instruction.
51///
52/// Transfers up to `max_amount` tokens from the user into the vault and
53/// mints vault shares in return. `remaining_accounts` must contain the refresh
54/// list: writable reserve metas followed by readonly lending-market metas, in
55/// allocation-slot order.
56pub fn deposit(
57    accounts: DepositAccounts,
58    max_amount: u64,
59    remaining_accounts: Vec<AccountMeta>,
60) -> Instruction {
61    #[derive(BorshSerialize)]
62    struct Args {
63        max_amount: u64,
64    }
65
66    let args = Args { max_amount };
67    let mut data = discriminators::DEPOSIT.to_vec();
68    args.serialize(&mut data).unwrap();
69
70    let mut account_metas = build_deposit_accounts(&accounts);
71    account_metas.extend(remaining_accounts);
72
73    Instruction {
74        program_id: KVAULT_PROGRAM_ID,
75        accounts: account_metas,
76        data,
77    }
78}
79
80// ---------------------------------------------------------------------------
81// buy (same accounts and args as deposit, different discriminator)
82// ---------------------------------------------------------------------------
83
84/// Build a raw `buy` instruction.
85///
86/// Same accounts and semantics as [`deposit`], but uses the `buy`
87/// discriminator. The amount is interpreted as the maximum tokens to spend.
88pub fn buy(
89    accounts: DepositAccounts,
90    max_amount: u64,
91    remaining_accounts: Vec<AccountMeta>,
92) -> Instruction {
93    #[derive(BorshSerialize)]
94    struct Args {
95        max_amount: u64,
96    }
97
98    let args = Args { max_amount };
99    let mut data = discriminators::BUY.to_vec();
100    args.serialize(&mut data).unwrap();
101
102    let mut account_metas = build_deposit_accounts(&accounts);
103    account_metas.extend(remaining_accounts);
104
105    Instruction {
106        program_id: KVAULT_PROGRAM_ID,
107        accounts: account_metas,
108        data,
109    }
110}