shadow_drive_sdk/
client.rs1use serde::de::DeserializeOwned;
2use std::{collections::HashMap, time::Duration};
3
4use serde_json::{json, Value};
5use solana_client::nonblocking::rpc_client::RpcClient;
6use solana_sdk::{commitment_config::CommitmentConfig, signer::Signer, transaction::Transaction};
7
8mod add_immutable_storage;
9mod add_storage;
10mod cancel_delete_storage_account;
11mod claim_stake;
12mod create_storage_account;
13mod delete_file;
14mod delete_storage_account;
15mod edit_file;
16mod get_storage_account;
17mod list_objects;
18mod make_storage_immutable;
19mod migrate;
20mod redeem_rent;
21mod reduce_storage;
22mod refresh_stake;
23mod store_files;
24mod top_up;
25use crate::{
28 constants::SHDW_DRIVE_ENDPOINT,
29 error::Error,
30 models::{FileDataResponse, GetBucketSizeResponse, ShadowDriveResult},
31};
32pub use add_immutable_storage::*;
33pub use add_storage::*;
34pub use cancel_delete_storage_account::*;
35pub use claim_stake::*;
36pub use create_storage_account::*;
37pub use delete_file::*;
38pub use delete_storage_account::*;
39pub use edit_file::*;
40pub use get_storage_account::*;
41pub use list_objects::*;
42pub use make_storage_immutable::*;
43pub use migrate::*;
44pub use redeem_rent::*;
45pub use reduce_storage::*;
46pub use refresh_stake::*;
47pub use store_files::*;
48pub use top_up::*;
49
50pub struct ShadowDriveClient<T>
52where
53 T: Signer,
54{
55 wallet: T,
56 rpc_client: RpcClient,
57 http_client: reqwest::Client,
58}
59
60impl<T> ShadowDriveClient<T>
61where
62 T: Signer,
63{
64 pub fn new<U: ToString>(wallet: T, rpc_url: U) -> Self {
82 let rpc_client = RpcClient::new_with_timeout_and_commitment(
83 rpc_url.to_string(),
84 Duration::from_secs(120),
85 CommitmentConfig::confirmed(),
86 );
87 Self {
88 wallet,
89 rpc_client,
90 http_client: reqwest::Client::new(),
91 }
92 }
93
94 pub fn new_with_rpc(wallet: T, rpc_client: RpcClient) -> Self {
111 Self {
112 wallet,
113 rpc_client,
114 http_client: reqwest::Client::new(),
115 }
116 }
117
118 pub async fn get_object_data(&self, location: &str) -> ShadowDriveResult<FileDataResponse> {
119 let response = self
120 .http_client
121 .post(format!("{}/get-object-data", SHDW_DRIVE_ENDPOINT))
122 .header("Content-Type", "application/json")
123 .json(&json!({ "location": location }))
124 .send()
125 .await?;
126
127 if !response.status().is_success() {
128 return Err(Error::ShadowDriveServerError {
129 status: response.status().as_u16(),
130 message: response.json::<Value>().await?,
131 });
132 }
133
134 let response = response.json::<FileDataResponse>().await?;
135
136 Ok(response)
137 }
138 pub async fn get_storage_account_size(
139 &self,
140 storage_account_key: &str,
141 ) -> ShadowDriveResult<GetBucketSizeResponse> {
142 let mut bucket_query = HashMap::new();
143 bucket_query.insert("storageAccount", storage_account_key.to_string());
144 let response = self
145 .http_client
146 .get(format!("{}/storage-account-size", SHDW_DRIVE_ENDPOINT))
147 .query(&bucket_query)
148 .header("Content-Type", "application/json")
149 .send()
150 .await?;
151
152 if !response.status().is_success() {
153 return Err(Error::ShadowDriveServerError {
154 status: response.status().as_u16(),
155 message: response.json::<Value>().await?,
156 });
157 }
158
159 let response = response.json::<GetBucketSizeResponse>().await?;
160
161 Ok(response)
162 }
163
164 async fn send_shdw_txn<K: DeserializeOwned>(
165 &self,
166 uri: &str,
167 txn_encoded: String,
168 storage_used: Option<u64>,
169 ) -> ShadowDriveResult<K> {
170 let body = serde_json::to_string(&json!({
171 "transaction": txn_encoded,
172 "commitment": "finalized",
173 "storageUsed": Some(storage_used)
174 }))
175 .map_err(Error::InvalidJson)?;
176
177 let response = self
178 .http_client
179 .post(format!("{}/{}", SHDW_DRIVE_ENDPOINT, uri))
180 .header("Content-Type", "application/json")
181 .body(body)
182 .send()
183 .await?;
184
185 if !response.status().is_success() {
186 return Err(Error::ShadowDriveServerError {
187 status: response.status().as_u16(),
188 message: response.json::<Value>().await?,
189 });
190 }
191
192 let response = response.json::<K>().await?;
193
194 Ok(response)
195 }
196}
197
198pub(crate) fn serialize_and_encode(txn: &Transaction) -> ShadowDriveResult<String> {
199 let serialized = bincode::serialize(txn)
200 .map_err(|error| Error::TransactionSerializationFailed(format!("{:?}", error)))?;
201 Ok(base64::encode(serialized))
202}