shadow_drive_sdk/client/
add_immutable_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;
5
6use solana_sdk::{
7 instruction::Instruction, pubkey::Pubkey, signer::Signer, transaction::Transaction,
8};
9use spl_associated_token_account::get_associated_token_address;
10use spl_token::ID as TokenProgramID;
11
12use super::ShadowDriveClient;
13use crate::models::storage_acct::{StorageAccount, StorageAccountV2, StorageAcct};
14use crate::serialize_and_encode;
15use crate::{
16 constants::{EMISSIONS, PROGRAM_ADDRESS, STORAGE_CONFIG_PDA, TOKEN_MINT, UPLOADER},
17 error::Error,
18 models::*,
19};
20
21impl<T> ShadowDriveClient<T>
22where
23 T: Signer,
24{
25 pub async fn add_immutable_storage(
54 &self,
55 storage_account_key: &Pubkey,
56 size: Byte,
57 ) -> ShadowDriveResult<StorageResponse> {
58 let size_as_bytes: u64 = size
59 .get_bytes()
60 .try_into()
61 .map_err(|_| Error::InvalidStorage)?;
62
63 let selected_storage_acct = self.get_storage_account(storage_account_key).await?;
64
65 let txn_encoded = match selected_storage_acct {
66 StorageAcct::V1(storage_account) => {
67 if !storage_account.immutable {
68 return Err(Error::StorageAccountIsNotImmutable);
69 }
70 self.add_immutable_storage_v1(storage_account_key, storage_account, size_as_bytes)
71 .await?
72 }
73 StorageAcct::V2(storage_account) => {
74 if !storage_account.immutable {
75 return Err(Error::StorageAccountIsNotImmutable);
76 }
77 self.add_immutable_storage_v2(storage_account_key, storage_account, size_as_bytes)
78 .await?
79 }
80 };
81
82 self.send_shdw_txn("add-storage", txn_encoded, None).await
83 }
84
85 async fn add_immutable_storage_v1(
86 &self,
87 storage_account_key: &Pubkey,
88 storage_account: StorageAccount,
89 size_as_bytes: u64,
90 ) -> ShadowDriveResult<String> {
91 let wallet_pubkey = &self.wallet.pubkey();
92 let owner_ata = get_associated_token_address(wallet_pubkey, &TOKEN_MINT);
93 let emissions_ata = get_associated_token_address(&EMISSIONS, &TOKEN_MINT);
94
95 let accounts = shdw_drive_accounts::IncreaseImmutableStorageV1 {
96 storage_config: *STORAGE_CONFIG_PDA,
97 storage_account: *storage_account_key,
98 emissions_wallet: emissions_ata,
99 owner: storage_account.owner_1,
100 owner_ata,
101 uploader: UPLOADER,
102 token_mint: TOKEN_MINT,
103 system_program: system_program::ID,
104 token_program: TokenProgramID,
105 };
106 let args = shdw_drive_instructions::IncreaseImmutableStorage {
107 additional_storage: size_as_bytes,
108 };
109
110 let instruction = Instruction {
111 program_id: PROGRAM_ADDRESS,
112 accounts: accounts.to_account_metas(None),
113 data: args.data(),
114 };
115
116 let mut txn = Transaction::new_with_payer(&[instruction], Some(wallet_pubkey));
117
118 txn.try_partial_sign(
119 &[&self.wallet],
120 self.rpc_client.get_latest_blockhash().await?,
121 )?;
122
123 let txn_encoded = serialize_and_encode(&txn)?;
124
125 Ok(txn_encoded)
126 }
127
128 async fn add_immutable_storage_v2(
129 &self,
130 storage_account_key: &Pubkey,
131 storage_account: StorageAccountV2,
132 size_as_bytes: u64,
133 ) -> ShadowDriveResult<String> {
134 let wallet_pubkey = &self.wallet.pubkey();
135 let owner_ata = get_associated_token_address(wallet_pubkey, &TOKEN_MINT);
136 let emissions_ata = get_associated_token_address(&EMISSIONS, &TOKEN_MINT);
137
138 let accounts = shdw_drive_accounts::IncreaseImmutableStorageV2 {
139 storage_config: *STORAGE_CONFIG_PDA,
140 storage_account: *storage_account_key,
141 emissions_wallet: emissions_ata,
142 owner: storage_account.owner_1,
143 owner_ata,
144 uploader: UPLOADER,
145 token_mint: TOKEN_MINT,
146 system_program: system_program::ID,
147 token_program: TokenProgramID,
148 };
149
150 let args = shdw_drive_instructions::IncreaseImmutableStorage2 {
151 additional_storage: size_as_bytes,
152 };
153
154 let instruction = Instruction {
155 program_id: PROGRAM_ADDRESS,
156 accounts: accounts.to_account_metas(None),
157 data: args.data(),
158 };
159
160 let mut txn = Transaction::new_with_payer(&[instruction], Some(wallet_pubkey));
161
162 txn.try_partial_sign(
163 &[&self.wallet],
164 self.rpc_client.get_latest_blockhash().await?,
165 )?;
166
167 let txn_encoded = serialize_and_encode(&txn)?;
168
169 Ok(txn_encoded)
170 }
171}