shadow_drive_sdk/client/
add_storage.rs1use anchor_lang::{system_program, InstructionData, ToAccountMetas};
2use byte_unit::Byte;
3use shadow_drive_user_staking::accounts as shdw_drive_accounts;
4use shadow_drive_user_staking::instruction as shdw_drive_instructions;
5use solana_client::{
6 client_error::{ClientError, ClientErrorKind},
7 rpc_request::RpcError,
8};
9use solana_sdk::{
10 instruction::Instruction, pubkey::Pubkey, signer::Signer, transaction::Transaction,
11};
12use spl_associated_token_account::get_associated_token_address;
13use spl_token::ID as TokenProgramID;
14
15use super::ShadowDriveClient;
16use crate::constants::UPLOADER;
17use crate::models::storage_acct::{StorageAccount, StorageAccountV2, StorageAcct};
18use crate::serialize_and_encode;
19use crate::{
20 constants::{PROGRAM_ADDRESS, STORAGE_CONFIG_PDA, TOKEN_MINT},
21 derived_addresses,
22 error::Error,
23 models::*,
24};
25
26impl<T> ShadowDriveClient<T>
27where
28 T: Signer,
29{
30 pub async fn add_storage(
60 &self,
61 storage_account_key: &Pubkey,
62 size: Byte,
63 ) -> ShadowDriveResult<StorageResponse> {
64 let size_as_bytes: u64 = size
65 .get_bytes()
66 .try_into()
67 .map_err(|_| Error::InvalidStorage)?;
68
69 let wallet_pubkey = self.wallet.pubkey();
70 let (user_info, _) = derived_addresses::user_info(&wallet_pubkey);
71
72 let user_info_acct = self.rpc_client.get_account(&user_info).await;
73 match user_info_acct {
74 Ok(_) => {
75 }
78 Err(ClientError {
79 kind: ClientErrorKind::RpcError(RpcError::ForUser(_)),
80 ..
81 }) => {
82 return Err(Error::UserInfoNotCreated);
85 }
86 Err(err) => {
87 return Err(Error::from(err));
89 }
90 }
91
92 let selected_storage_acct = self.get_storage_account(storage_account_key).await?;
93
94 let txn_encoded = match selected_storage_acct {
95 StorageAcct::V1(storage_account) => {
96 self.add_storage_v1(storage_account_key, storage_account, size_as_bytes)
97 .await?
98 }
99 StorageAcct::V2(storage_account) => {
100 self.add_storage_v2(storage_account_key, storage_account, size_as_bytes)
101 .await?
102 }
103 };
104
105 self.send_shdw_txn("add-storage", txn_encoded, None).await
106 }
107
108 async fn add_storage_v1(
109 &self,
110 storage_account_key: &Pubkey,
111 storage_account: StorageAccount,
112 size_as_bytes: u64,
113 ) -> ShadowDriveResult<String> {
114 let wallet_pubkey = &self.wallet.pubkey();
115 let owner_ata = get_associated_token_address(wallet_pubkey, &TOKEN_MINT);
116 let (stake_account, _) = derived_addresses::stake_account(storage_account_key);
117
118 let accounts = shdw_drive_accounts::IncreaseStorageV1 {
119 storage_config: *STORAGE_CONFIG_PDA,
120 storage_account: *storage_account_key,
121 owner: storage_account.owner_1,
122 owner_ata,
123 stake_account,
124 uploader: UPLOADER,
125 token_mint: TOKEN_MINT,
126 system_program: system_program::ID,
127 token_program: TokenProgramID,
128 };
129 let args = shdw_drive_instructions::IncreaseStorage {
130 additional_storage: size_as_bytes,
131 };
132
133 let instruction = Instruction {
134 program_id: PROGRAM_ADDRESS,
135 accounts: accounts.to_account_metas(None),
136 data: args.data(),
137 };
138
139 let mut txn = Transaction::new_with_payer(&[instruction], Some(wallet_pubkey));
140
141 txn.try_partial_sign(
142 &[&self.wallet],
143 self.rpc_client.get_latest_blockhash().await?,
144 )?;
145
146 let txn_encoded = serialize_and_encode(&txn)?;
147
148 Ok(txn_encoded)
149 }
150
151 async fn add_storage_v2(
152 &self,
153 storage_account_key: &Pubkey,
154 storage_account: StorageAccountV2,
155 size_as_bytes: u64,
156 ) -> ShadowDriveResult<String> {
157 let wallet_pubkey = &self.wallet.pubkey();
158 let owner_ata = get_associated_token_address(wallet_pubkey, &TOKEN_MINT);
159 let (stake_account, _) = derived_addresses::stake_account(storage_account_key);
160
161 let accounts = shdw_drive_accounts::IncreaseStorageV2 {
162 storage_config: *STORAGE_CONFIG_PDA,
163 storage_account: *storage_account_key,
164 owner: storage_account.owner_1,
165 owner_ata,
166 stake_account,
167 uploader: UPLOADER,
168 token_mint: TOKEN_MINT,
169 system_program: system_program::ID,
170 token_program: TokenProgramID,
171 };
172
173 let args = shdw_drive_instructions::IncreaseStorage2 {
174 additional_storage: size_as_bytes,
175 };
176
177 let instruction = Instruction {
178 program_id: PROGRAM_ADDRESS,
179 accounts: accounts.to_account_metas(None),
180 data: args.data(),
181 };
182
183 let mut txn = Transaction::new_with_payer(&[instruction], Some(wallet_pubkey));
184
185 txn.try_partial_sign(
186 &[&self.wallet],
187 self.rpc_client.get_latest_blockhash().await?,
188 )?;
189
190 let txn_encoded = serialize_and_encode(&txn)?;
191
192 Ok(txn_encoded)
193 }
194}